http://codeforces.com/problemset/problem/241/E
首先检测哪些点会出现在从起点到终点的路上,可以用dfs或者迭代,
然后,对于所有的边,设f为边起点,t为边终点,dp[i]为从起点出发到i点所必须花费的时间,则当dp[t]>dp[f]+2,也就是超出限制时,把dp[t]限制到dp[f]+2处,对于dp[f]>dp[t]+1,限制dp[f]到dp[t]+1处
因为这个图没有圈,所以如果存在满足题意的边权方案,那么每次使得一个点的dp值满足要求,n次之后一定全部满足要求,不再发生改动,如果不存在满足题意的边权方案,就会不断发生震荡,此时及时停止循环输出No即可
注意不在起点到终点路上的边全都为1
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 const int maxn=1e3+2; 5 const int maxm=5e3+2; 6 const int inf=0x3fffffff; 7 int n,m; 8 int vis[maxn]; 9 int e[maxm][2]; 10 int dp[maxn]; 11 int main(){ 12 scanf("%d%d",&n,&m); 13 for(int i=0;i<m;i++)scanf("%d%d",e[i],e[i]+1); 14 vis[1]=1;vis[n]=2; 15 bool fl=true; 16 while(fl){ 17 fl=false; 18 for(int i=0;i<m;i++){ 19 int f=e[i][0],t=e[i][1]; 20 if((vis[f]&1)&&(vis[t]&1)==0){ 21 vis[t]|=1;fl=true; 22 } 23 if((vis[t]&2)&&(vis[f]&2)==0){ 24 vis[f]|=2;fl=true; 25 } 26 } 27 } 28 fl=true; 29 int cnt=0; 30 while(fl){ 31 fl=false; 32 cnt++; 33 for(int i=0;i<m;i++){ 34 int f=e[i][0],t=e[i][1]; 35 if(vis[f]==3&&vis[t]==3){ 36 if(dp[t]>dp[f]+2){ 37 dp[t]=dp[f]+2; 38 fl=true; 39 } 40 if(dp[f]>dp[t]-1){ 41 dp[f]=dp[t]-1; 42 fl=true; 43 } 44 } 45 } 46 if(cnt>n&&fl){puts("No");return 0;} 47 } 48 puts("Yes"); 49 for(int i=0;i<m;i++){ 50 int f=e[i][0],t=e[i][1]; 51 if(vis[f]==3&&vis[t]==3)printf("%d\n",dp[t]-dp[f]); 52 else puts("1"); 53 } 54 return 0; 55 }
时间: 2024-10-18 01:28:00