Educational Codeforces Round 40 (Rated for Div. 2) D. Fight Against Traffic(最短路径)
http://codeforces.com/contest/954/problem/D
题意:给你n个点m条路径(无向),再给你一个起点s、一个终点t,此时可以得到s到t的最短距离,让求增加多少条边使得s到t的最短距离不变。
题解:就是求最短路径的题,我们可以先求出起点s到每个点的最短路径ds[],再求t点到每个点的最短距离dt[],我们可以得到s到t的最短距离D=ds[t]=dt[s],然后遍历一遍所有的点(u,v),让他们满足u,v两点直接没有边并且ds[u]+dt[v]+1<=D&&ds[v]+dt[u]+1<=D。
这道题可以用两种求最短路径的方法求.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inff=0x3f3f3f; 4 const int maxn=1005; 5 int n,m; 6 int s,t; 7 int ds[maxn];/*s点到各个点的最小距离*/ 8 int dt[maxn]; 9 int edge[maxn][maxn]; 10 int pos[maxn]; 11 void DIJ(int st,int dis[]) 12 { 13 for(int i=1; i<=n; i++) 14 { 15 pos[i]=0; 16 dis[i]=inff; 17 } 18 dis[st]=0; 19 for(int i=1; i<=n; i++) 20 { 21 int minj,MM; 22 MM=inff; 23 for(int j=1; j<=n; j++) 24 if(!pos[j]&&dis[j]<=MM) 25 { 26 MM=dis[j]; 27 minj=j; 28 } 29 pos[minj]=1; 30 for(int j=1; j<=n; j++) 31 dis[j]=min(dis[j],dis[minj]+edge[minj][j]); 32 } 33 } 34 int main() 35 { 36 while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF) 37 { 38 memset(edge,inff,sizeof(edge)); 39 for(int i=1;i<=m;i++) 40 { 41 int x,y; 42 scanf("%d%d",&x,&y); 43 edge[x][y]=1; 44 edge[y][x]=1; 45 } 46 DIJ(s,ds); 47 DIJ(t,dt); 48 int D=ds[t]; 49 int ans=0; 50 for(int u=1;u<=n;u++) 51 { 52 for(int v=1;v<=n;v++) 53 { 54 if(u==v) 55 continue; 56 if(edge[u][v]!=1) 57 { 58 if(ds[u]+dt[v]+1>=D&&ds[v]+dt[u]+1>=D) 59 { 60 ans++; 61 edge[u][v]=1; 62 edge[v][u]=1; 63 } 64 } 65 } 66 } 67 printf("%d\n",ans); 68 } 69 return 0; 70 }
2018-03-24
11:02:22
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int inff=0x3f3f3f; 5 const int maxn=1005; 6 int n,m; 7 int s,t; 8 int ds[maxn];/*s�㵽���������С����*/ 9 int dt[maxn]; 10 int edge[maxn][maxn]; 11 vector<int>v[maxn]; 12 int pos[maxn]; 13 14 void SPAF(int st,int dis[]) 15 { 16 for(int i=1;i<=n;i++) 17 { 18 dis[i]=inff; 19 pos[i]=0; 20 } 21 queue<int>q; 22 while(q.size()) 23 q.pop(); 24 q.push(st); 25 pos[st]=1; 26 dis[st]=0; 27 while(q.size()) 28 { 29 st=q.front(); 30 q.pop(); 31 pos[st]=0; 32 int ss=v[st].size(); 33 for(int i=0;i<ss;i++) 34 { 35 int en=v[st][i]; 36 if(dis[en]>dis[st]+1) 37 { 38 dis[en]=dis[st]+1; 39 if(pos[en]==0) 40 { 41 q.push(en); 42 pos[en]=1; 43 } 44 } 45 } 46 } 47 } 48 int main() 49 { 50 while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF) 51 { 52 memset(edge,0,sizeof(edge)); 53 for(int i=1;i<=n;i++) 54 v[i].clear(); 55 for(int i=1;i<=m;i++) 56 { 57 int x,y; 58 scanf("%d%d",&x,&y); 59 edge[x][y]=1; 60 edge[y][x]=1; 61 v[x].push_back(y); 62 v[y].push_back(x); 63 } 64 SPAF(s,ds); 65 SPAF(t,dt); 66 int D=ds[t]; 67 int ans=0; 68 for(int u=1;u<=n;u++) 69 { 70 for(int v=1;v<=n;v++) 71 { 72 if(u==v) 73 continue; 74 if(edge[u][v]==0) 75 { 76 if(ds[u]+dt[v]+1>=D&&ds[v]+dt[u]+1>=D) 77 { 78 ans++; 79 edge[u][v]=1; 80 edge[v][u]=1; 81 //printf("u=%d v=%d\n",u,v); 82 } 83 } 84 } 85 } 86 printf("%d\n",ans); 87 } 88 return 0; 89 }
做这道题的感想!~!~~:
之所以把这道题记录下来是因为,刚开始的时候我使用的是DIJ求最短距离,结果在对edge[][]数组初始值为0了,让自己在第一组样例一直出错,之后发现是在求最短距离这里出错的,但是就是找不到在哪里错,想了很久才发现这个错误点,edge[][]初始值应该为inf就是两点之间没有直接相连的边是他们的edge为inf.
当时很久找不出DIJ哪里出错就用的SPFA来做的,AC之后才返回来寻找了一下自己的DIJ出错的地方。