前言
9月做的题现在不会了???
越学越拉了属于是。
解析
设 disxdis_xdisx 表示 1-x 的最小距离,那么一条 u->v 的边的边权就是 disv−disudis_v-dis_udisv−disu。
差分约束即可。
挂掉的坑点:只需要考虑1可以到达的点!
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned ll
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")inline ll read() {ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
const int N=2e4+100;
const int mod=1e9+7;
const int inf=1e9+100;
const double eps=1e-9;bool mem1;bool Flag=0;inline ll ksm(ll x,ll k,int mod){ll res(1);x%=mod;while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res;
}int n,m;int dp[N];
vector<int>e[N];
int u[N],v[N];
struct node{int to,nxt,w;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y,int w){p[++cnt]=(node){y,fi[x],w};fi[x]=cnt;
}int find(int x){if(dp[x]!=-1) return dp[x];if(x==n) return dp[x]=1;dp[x]=0;for(int to:e[x]) dp[x]|=find(to);return dp[x];
}
queue<int>q;
int dis[N],len[N];
bool vis[N];
void spfa(){memset(dis,0x3f,sizeof(dis));dis[1]=0;q.push(1);while(!q.empty()){int x=q.front();q.pop();vis[x]=0;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(!dp[to]) continue;if(dis[to]>dis[x]+p[i].w){dis[to]=dis[x]+p[i].w;len[to]=len[x]+1;if(len[to]>n){puts("-1");exit(0);}if(!vis[to]){q.push(to);vis[to]=1;}}}}return;
}bool mem2;
signed main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endif//debug("mem=%.4lf\n",abs(&mem2-&mem1)/1024./1024);memset(dp,-1,sizeof(dp));memset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1;i<=m;i++){u[i]=read();v[i]=read();e[u[i]].push_back(v[i]);}find(1);for(int i=1;i<=n;i++){if(dp[i]==-1) dp[i]=0;}if(!dp[1]){puts("-1");return 0;}for(int i=1;i<=m;i++){if(dp[v[i]]==0) continue;addline(u[i],v[i],9);addline(v[i],u[i],-1);}spfa();printf("%d %d\n",n,m);for(int i=1;i<=m;i++){int res=dis[v[i]]-dis[u[i]];res=max(res,1);res=min(res,9);printf("%d %d %d\n",u[i],v[i],res);}return 0;
}
/*
*/