题意:有 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