Codeforces Round #581 (div. 2) Tutorial C(floyed最短路记录关键节点)
floyed最短路记录关键节点
比赛的时候想到最短路了,但是不知道怎么处理。
后来看了题解,因为以一个点一定要,所以记录第一个节点
对于第二个要不要呢,实际上是取决于第三个点的,如果求出的最短路a1—>a3是小于(3-1)的,如果不记录第二个节点,那么第二个节点就会被抛弃,所以第二个节点记录。
如果a1—>a3等于(3-1)的,那么一定可以走1—>2—>3这条路到达3。2就一定不用记录。
接下来依次类推,如果某个节点记录了,那么就让他发挥一开始a1的作用。最后别忘了把am放进去。那么就是所求路径了。
感觉有点贪心的意思。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=100+5; 5 const int inf=9999999; 6 int mp[maxn][maxn]; 7 int b[1000005]; 8 int n; 9 int main(){ 10 cin>>n; 11 for(int i=1;i<=n;i++){ 12 string str;cin>>str; 13 for(int j=0;j<str.size();j++) 14 { 15 mp[i][j+1]=str[j]-'0'; 16 if(mp[i][j+1]==0) mp[i][j+1]=inf; 17 if(i==j+1) mp[i][j+1]=0; 18 } 19 } 20 /* for(int i=1;i<=n;i++){ 21 22 { 23 for(int j=1;j<=n;j++) 24 cout <<mp[i][j]<<" "; 25 } 26 cout <<endl; 27 }*/ 28 for(int k=1;k<=n;k++){ 29 for(int i=1;i<=n;i++) 30 for(int j=1;j<=n;j++) 31 mp[i][j]=min(mp[i][k]+mp[k][j],mp[i][j]); 32 } 33 /* for(int i=1;i<=n;i++){ 34 35 { 36 for(int j=1;j<=n;j++) 37 cout <<mp[i][j]<<" "; 38 } 39 cout <<endl; 40 }*/ 41 int m;cin>>m; 42 for(int i=1;i<=m;i++) cin>>b[i]; 43 vector <int>V; 44 V.push_back(b[1]); 45 int now=b[1];int dis=1; 46 for(int i=3;i<=m;i++) 47 { 48 dis++; 49 if(dis>mp[now][b[i]]) 50 { 51 V.push_back(b[i-1]); 52 now=b[i-1]; 53 dis=1; 54 } 55 } 56 V.push_back(b[m]); 57 cout <<V.size()<<"\n"; 58 for(int i=0;i<V.size();i++) cout <<V[i]<<" "; 59 cout <<"\n"; 60 61 62 63 64 65 return 0; 66 }