poj3114 强连通+最短路
2015-09-17 20:12
447 查看
题意:有 n 个城市,城市之间能够通过邮件或者电子邮件传递消息,已知 m 条邮件线路,每条线路代表 A 能送邮件到 B,并且花费 V 时间,如果几个城市之间能够相互邮件送达,那么他们就在同一个国家内,他们之间就能够通过电子邮件传递消息,花费 0 时间。有 k 个询问,每次询问从点 a 到点 b 传送消息,最少需要花费多少时间。
由于多个城市能够互相送邮件,那么就在同一国家,互相传递消息不需要花费,因此首先强连通缩点,然后再对每次询问求出解就行。我一开始认为强连通缩点后是有向无环图,直接 dfs 的话对于每个询问复杂度不会很大,但是结果T了,然后换成了每个询问求一次单源最短路,然后A掉了。
View Code
由于多个城市能够互相送邮件,那么就在同一国家,互相传递消息不需要花费,因此首先强连通缩点,然后再对每次询问求出解就行。我一开始认为强连通缩点后是有向无环图,直接 dfs 的话对于每个询问复杂度不会很大,但是结果T了,然后换成了每个询问求一次单源最短路,然后A掉了。
#include<stdio.h> #include<string.h> #include<stack> #include<queue> #include<algorithm> #include<vector> using namespace std; typedef pair<int,int> pii; const int maxn=505; const int maxm=250005; const int INF=0x3f3f3f3f; int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2],val[2][maxm]; int n,t,scccnt; int stx[maxn],low[maxn],scc[maxn]; int dis[maxn]; stack<int>S; int min(int a,int b){return a<b?a:b;} void init(){ memset(head,-1,sizeof(head)); size[0]=size[1]=0; } void add(int a,int b,int v,int c=0){ point[c][size[c]]=b; nxt[c][size[c]]=head[c][a]; val[c][size[c]]=v; head[c][a]=size[c]++; } struct cmp{ //将优先队列改为小根堆 bool operator()(pii a,pii b){ return a.first>b.first; } }; void dij(int s,int t){ //传入出发点和到达点 int i; priority_queue<pii,vector<pii>,cmp>q; q.push(make_pair(0,s)); memset(dis,0x3f,sizeof(dis)); dis[s]=0; while(!q.empty()){ pii u=q.top(); q.pop(); if(u.first>dis[u.second])continue; for(i=head[1][u.second];~i;i=nxt[1][i]){ int j=point[1][i]; if(dis[j]>u.first+val[1][i]){ dis[j]=u.first+val[1][i]; q.push(make_pair(dis[j],j)); } } } if(dis[t]==INF)printf("Nao e possivel entregar a carta\n"); else printf("%d\n",dis[t]); } void dfs(int s){ stx[s]=low[s]=++t; S.push(s); for(int i=head[0][s];~i;i=nxt[0][i]){ int j=point[0][i]; if(!stx[j]){ dfs(j); low[s]=min(low[s],low[j]); } else if(!scc[j]){ low[s]=min(low[s],stx[j]); } } if(low[s]==stx[s]){ scccnt++; while(1){ int u=S.top();S.pop(); scc[u]=scccnt; if(s==u)break; } } } void setscc(){ memset(stx,0,sizeof(stx)); memset(scc,0,sizeof(scc)); t=scccnt=0; for(int i=1;i<=n;++i)if(!stx[i])dfs(i); for(int i=1;i<=n;++i){ for(int j=head[0][i];~j;j=nxt[0][j]){ int k=point[0][j]; if(scc[i]!=scc[k]){ add(scc[i],scc[k],val[0][j],1); } } } } int main(){ int m; while(scanf("%d",&n)!=EOF&&n){ scanf("%d",&m); init(); while(m--){ int a,b,v; scanf("%d%d%d",&a,&b,&v); add(a,b,v); } setscc(); int k; scanf("%d",&k); while(k--){ int a,b; scanf("%d%d",&a,&b); if(scc[a]==scc[b])printf("0\n"); else{ dij(scc[a],scc[b]); } } printf("\n"); } return 0; }
View Code
相关文章推荐
- 适者生存
- 第八周第四天
- Objective-C学习大纲
- Bitmap,使用Matrix对图像几何变换
- Android布局属性LayoutParams的理解
- HDU 整除的尾数 2099
- CTC模型
- BDFProxy
- SQL SERVER中 用FOR XML PATH将查询结果以XML输出 然后应用于 sql 合并字段功能介绍
- LATEX双栏最后一页如何平衡两栏内容
- hdu5135Little Zu Chongzhi's Triangles dfs
- HTML5中canvas的save和restore方法
- 归并排序方法
- Oracle 触发器数据同步
- AngularJS进阶(六)AngularJS+BootStrap实现弹出对话框
- Android MediaPlayer 播放本地与远程的mp3初步
- 单例懒汉式的多线程操作的安全问题
- shell脚本 集成测试多个UiAutomator case类
- AngularJS进阶(六)AngularJS+BootStrap实现弹出对话框
- css问题