JZOJ 1782. Travel
题目
分析
- 我们要判断两点间是否相互连通
- 不单单只是两点能直接到达
- 间接到达也是可以的
- 所以我们跑一个Floyd
- 就能判断是否连通啦
- 然后要注意的一点是,我每一次跟新一次值都要放队列重新对其他点进行跟新
代码
#include<iostream> #include<vector> #include<queue> #include<cstring> using namespace std; int vis[201][201]; int dp[201][20]; int map[201][201]; int flag[201]; int fl[201][201]; int n,m,k; vector<int> f[201]; void spfa() { memset(dp,0x3f,sizeof(dp)); queue<int> q; q.push(1); dp[1][0]=0; flag[1]=1; while (!q.empty()) { int x=q.front(); q.pop(); flag[x]=0; for (int i=0;i<f[x].size();i++) { int y=f[x][i]; if (fl[y][x]!=fl[0][0]) { for (int j=0;j<=k;j++) if(dp[x][j]+map[x][y]<dp[y][j]) { dp[y][j]=min(dp[y][j],dp[x][j]+map[x][y]); if(!flag[y]) { flag[y]=1; q.push(y); } } } else { for (int j=1;j<=k;j++) if(dp[x][j-1]+map[x][y]*2<dp[y][j]) { dp[y][j]=min(dp[x][j-1]+2*map[x][y],dp[y][j]); if(!flag[y]) { flag[y]=1; q.push(y); } } } } } } int main () { cin>>n>>m>>k; memset(map,0x3f,sizeof(map)); memset(fl,0x3f,sizeof(fl)); for (int i=1,x,y,z;i<=m;i++) { cin>>x>>y>>z; if (!vis[x][y]) { f[x].push_back(y); vis[x][y]=1; } map[x][y]=min(map[x][y],z); fl[x][y]=min(fl[x][y],z); } for (int kk=1;kk<=n;kk++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i!=j&&i!=kk&&j!=kk&&fl[i][kk]+fl[kk][j]<fl[i][j]) fl[i][j]=fl[i][kk]+fl[kk][j]; spfa(); int ans=1e9; for (int i=0;i<=k;i++) ans=min(dp[n][i],ans); if (ans==1000000000) cout<<-1; else cout<<ans; }
为何要逼自己长大,去闯不该闯的荒唐