poj3114 强连通+最短路

题意:有 n 个城市,城市之间能够通过邮件或者电子邮件传递消息,已知 m 条邮件线路,每条线路代表 A 能送邮件到 B,并且花费 V 时间,如果几个城市之间能够相互邮件送达,那么他们就在同一个国家内,他们之间就能够通过电子邮件传递消息,花费 0 时间。有 k 个询问,每次询问从点 a 到点 b 传送消息,最少需要花费多少时间。

由于多个城市能够互相送邮件,那么就在同一国家,互相传递消息不需要花费,因此首先强连通缩点,然后再对每次询问求出解就行。我一开始认为强连通缩点后是有向无环图,直接 dfs 的话对于每个询问复杂度不会很大,但是结果T了,然后换成了每个询问求一次单源最短路,然后A掉了。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stack>
  4 #include<queue>
  5 #include<algorithm>
  6 #include<vector>
  7 using namespace std;
  8 typedef pair<int,int> pii;
  9
 10 const int maxn=505;
 11 const int maxm=250005;
 12 const int INF=0x3f3f3f3f;
 13
 14 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2],val[2][maxm];
 15 int n,t,scccnt;
 16 int stx[maxn],low[maxn],scc[maxn];
 17 int dis[maxn];
 18 stack<int>S;
 19
 20 int min(int a,int b){return a<b?a:b;}
 21
 22 void init(){
 23     memset(head,-1,sizeof(head));
 24     size[0]=size[1]=0;
 25 }
 26
 27 void add(int a,int b,int v,int c=0){
 28     point[c][size[c]]=b;
 29     nxt[c][size[c]]=head[c][a];
 30     val[c][size[c]]=v;
 31     head[c][a]=size[c]++;
 32 }
 33
 34 struct cmp{                    //将优先队列改为小根堆
 35     bool operator()(pii a,pii b){
 36         return a.first>b.first;
 37     }
 38 };
 39
 40 void dij(int s,int t){            //传入出发点和到达点
 41     int i;
 42     priority_queue<pii,vector<pii>,cmp>q;
 43     q.push(make_pair(0,s));
 44     memset(dis,0x3f,sizeof(dis));
 45     dis[s]=0;
 46     while(!q.empty()){
 47         pii u=q.top();
 48         q.pop();
 49         if(u.first>dis[u.second])continue;
 50         for(i=head[1][u.second];~i;i=nxt[1][i]){
 51             int j=point[1][i];
 52             if(dis[j]>u.first+val[1][i]){
 53                 dis[j]=u.first+val[1][i];
 54                 q.push(make_pair(dis[j],j));
 55             }
 56         }
 57     }
 58     if(dis[t]==INF)printf("Nao e possivel entregar a carta\n");
 59     else printf("%d\n",dis[t]);
 60 }
 61
 62 void dfs(int s){
 63     stx[s]=low[s]=++t;
 64     S.push(s);
 65     for(int i=head[0][s];~i;i=nxt[0][i]){
 66         int j=point[0][i];
 67         if(!stx[j]){
 68             dfs(j);
 69             low[s]=min(low[s],low[j]);
 70         }
 71         else if(!scc[j]){
 72             low[s]=min(low[s],stx[j]);
 73         }
 74     }
 75     if(low[s]==stx[s]){
 76         scccnt++;
 77         while(1){
 78             int u=S.top();S.pop();
 79             scc[u]=scccnt;
 80             if(s==u)break;
 81         }
 82     }
 83 }
 84
 85 void setscc(){
 86     memset(stx,0,sizeof(stx));
 87     memset(scc,0,sizeof(scc));
 88     t=scccnt=0;
 89     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
 90     for(int i=1;i<=n;++i){
 91         for(int j=head[0][i];~j;j=nxt[0][j]){
 92             int k=point[0][j];
 93             if(scc[i]!=scc[k]){
 94                 add(scc[i],scc[k],val[0][j],1);
 95             }
 96         }
 97     }
 98 }
 99
100 int main(){
101     int m;
102     while(scanf("%d",&n)!=EOF&&n){
103         scanf("%d",&m);
104         init();
105         while(m--){
106             int a,b,v;
107             scanf("%d%d%d",&a,&b,&v);
108             add(a,b,v);
109         }
110         setscc();
111         int k;
112         scanf("%d",&k);
113         while(k--){
114             int a,b;
115             scanf("%d%d",&a,&b);
116             if(scc[a]==scc[b])printf("0\n");
117             else{
118                 dij(scc[a],scc[b]);
119             }
120         }
121         printf("\n");
122     }
123     return 0;
124 }

时间: 2024-10-08 10:13:39

poj3114 强连通+最短路的相关文章

POJ 3114 Countries in War 强连通+最短路

用floyd超时了...注定的事情...题意:看案例就跑出来了..不需要看题了把.. #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #include<vector> const int INF =1999299; int minn(int a,int b) { return a>b?b:a; } #define N 510 #define M

POJ 3114 Countries in War(强连通+最短路)

POJ 3114 Countries in War 题目链接 题意:给定一个有向图,强连通分支内传送不需要花费,其他有一定花费,每次询问两点的最小花费 思路:强连通缩点后求最短路即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <stack> #include <algorithm> using namespa

最短路径问题小结

最短路径问题包括: 1.单源最短路. 2.任意两点间的最短路. 3.次短路和k短路. 4.差分约束系统. 5.DAG图上的单源最短路. 6.最小环. 一.单源最短路 算法: Dijkstra . Bellman - Ford .SPFA Dijkstra: 除了路径记录和更新距离数组的部分意外,和Prim算法的实现完全一样.使用邻接矩阵建图,时间复杂度为O(n*n).使用邻接表可能会快一些.堆优化比较麻烦,没学.缺点是图中不能含有负圈. Bellman - Ford :可以处理负圈.以链式前向星

题单二:图论500

http://wenku.baidu.com/link?url=gETLFsWcgddEDRZ334EJOS7qCTab94qw5cor8Es0LINVaGMSgc9nIV-utRIDh--2UwRLvsvJ5tXFjbdpzbjygEdpGehim1i5BfzYgYWxJmu ==========  以下是最小生成树+并查集=========================[HDU]1213         How Many Tables        基础并查集★1272         小

图论五百题!

生死看淡不服就淦,这才是人生! =============================以下是最小生成树+并查集======================================[HDU]1213 How Many Tables 基础并查集★1272 小希的迷宫 基础并查集★1325&&poj1308 Is It A Tree? 基础并查集★1856 More is better 基础并查集★1102 Constructing Roads 基础最小生成树★1232 畅通工程 基

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

图论精炼500题

忘了从哪转的了... =============================以下是最小生成树+并查集====================================== [HDU] 1213               How Many Tables                    基础并查集★ 1272               小希的迷宫                     基础并查集★ 1325&&poj1308    Is It A Tree?       

hdu图论题目分类

=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 123

图论500题

=============================以下是最小生成树+并查集====================================== [HDU] 1213   How Many Tables   基础并查集★ 1272   小希的迷宫   基础并查集★ 1325&&poj1308  Is It A Tree?   基础并查集★ 1856   More is better   基础并查集★ 1102   Constructing Roads  基础最小生成树★ 12