• 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
    ");
     59     else printf("%d
    ",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
    ");
    117             else{
    118                 dij(scc[a],scc[b]);
    119             }
    120         }
    121         printf("
    ");
    122     }
    123     return 0;
    124 }
    View Code
  • 相关阅读:
    先森,我们是不同的字符串,请自重!
    Linux 内核 链表 的简单模拟(2)
    Linux 内核 链表 的简单模拟(1)
    Ubuntu 截屏
    ubuntu windows 双系统 磁盘乱搞 grub 导致 error:no such partition grub rescue>
    计算十进制数转化成二进制时1的个数
    Ubuntu gedit 折叠插件
    Unix 进程通信基本概念
    左式堆
    双调巡游
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4817542.html
Copyright © 2020-2023  润新知