• 2200: [Usaco2011 Jan]道路和航线 (拓扑排序+dijstra)


    Description

    Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T。这些城镇之间通过R条道路 (1 <= R <= 50,000,编号为1到R) 和P条航线 (1 <= P <= 50,000,编号为1到P) 连接。每条道路i或者航线i连接城镇A_i (1 <= A_i <= T)到B_i (1 <= B_i <= T),花费为C_i。对于道路,0 <= C_i <= 10,000;然而航线的花费很神奇,花费C_i可能是负数(-10,000 <= C_i <= 10,000)。道路是双向的,可以从A_i到B_i,也可以从B_i到A_i,花费都是C_i。然而航线与之不同,只可以从A_i到B_i。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台 了一些政策保证:如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_i。由于FJ的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇S(1 <= S <= T) 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。

    Input

    * 第1行:四个空格隔开的整数: T, R, P, and S * 第2到R+1行:三个空格隔开的整数(表示一条道路):A_i, B_i 和 C_i * 第R+2到R+P+1行:三个空格隔开的整数(表示一条航线):A_i, B_i 和 C_i

    Output

    * 第1到T行:从S到达城镇i的最小花费,如果不存在输出"NO PATH"。

    Sample Input



    6 3 3 4

    1 2 5

    3 4 5

    5 6 10

    3 5 -100

    4 6 -100

    1 3 -10



    样例输入解释:



    一共六个城镇。在1-2,3-4,5-6之间有道路,花费分别是5,5,10。同时有三条航线:3->5,

    4->6和1->3,花费分别是-100,-100,-10。FJ的中心城镇在城镇4。





    Sample Output



    NO PATH

    NO PATH

    5

    0

    -95

    -100



    样例输出解释:



    FJ的奶牛从4号城镇开始,可以通过道路到达3号城镇。然后他们会通过航线达到5和6号城镇。

    但是不可能到达1和2号城镇。

     
     
    思路:
    因为有负权边,所以不能使用dijstra,但是这个数据量使用spfa会t,所以我们考录heap+dijstra。
    如何解决负权边呢??注意题目:如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_i。
    这就说明,单向边一定不会形成环。
    所以一个联通块中,不可能有一个起点和终点都在这个强联通块的单向边,然且对于两个强连通块,只能出项从一个块指向另一个块的单向边,若相互指向,则会形成环
    那么对于一个联通块,我们可以只考虑双向边,直接使用dijstra,然后对从这个联通块发出的单向边进行更新,更新其他联通块中的dist,然后把处理过的单向边抹去。
     
    因为是从s到其他点的距离,所以如果从一个联通块,没有单向边指向它,并且还不是s所在联通块,那么它里面的点都是无法到达的(显然)
     
     
    ①所以,我们可以按照拓扑序进行更新,每处理完一个联通块,和其单向边,我们就消除单向边造成的入度,然后进行拓扑排序选择联通块。
    这样写法s所在联通块并不一定第一个入队,但是其前入队的联通块最短路无法更新,只能消除单向边,写法清晰。
     
    ②我们也一开始可以就把s的联通块号传入,这样的话,其他入度为0的联通块指出的单向边,我们直接需要将其抹去,消除无效联通块对其他联通快造成的入度。
    因为其他入度为0的联通块,是无效的。(代码注释部分)
     
     
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 int t,r,p,s;
      5 typedef pair<int,int> pii;
      6 const int maxn = 5e4+5;
      7 vector<int>belong[maxn];
      8 struct Node
      9 {
     10     int x,y,val,next;
     11     Node(int x=0,int y=0,int val=0,int next=0):x(x),y(y),val(val),next(next) {}
     12 } node[2][maxn<<2];
     13 
     14 int head[2][maxn];
     15 int cnt[2];
     16 int tot;
     17 void add(int x,int y,int val,int t)
     18 {
     19     node[t][++cnt[t]].x = x;
     20     node[t][cnt[t]].y = y;
     21     node[t][cnt[t]].val = val;
     22     node[t][cnt[t]].next = head[t][x];
     23     head[t][x] = cnt[t];
     24 }
     25 int cn[maxn];
     26 int ind[maxn];
     27 int dist[maxn];
     28 bool vis[maxn];
     29 void dfs(int x)
     30 {
     31     cn[x] = tot;
     32     belong[tot].push_back(x);
     33     for(int i=head[0][x]; i; i=node[0][i].next)
     34     {
     35         int y = node[0][i].y;
     36         if(cn[y])
     37             continue;
     38         dfs(y);
     39     }
     40 }
     41 void solve(int s)
     42 {
     43     queue<int>que;
     44     while(!que.empty())
     45         que.pop();
     46     for(int i=1; i<=tot; i++)
     47         if(!ind[i])
     48             que.push(i);
     49 //    for(int i=1; i<=tot; i++)
     50 //    {
     51 //        if(!ind[i] && i != cn[s])
     52 //        {
     53 //            for(int j=0; j<belong[i].size(); j++)
     54 //            {
     55 //                for(int k=head[1][belong[i][j]]; k; k=node[1][k].next)
     56 //                {
     57 //                    --ind[cn[node[1][k].y]];
     58 //                }
     59 //            }
     60 //            ind[i] = -1;
     61 //            //printf("%d ------ %d
    ",ind[i],i);
     62 //            i=0;
     63 //        }
     64 //    }
     65 //    que.push(cn[s]);
     66     memset(dist,0x3f,sizeof(dist));
     67     dist[s] = 0;
     68     priority_queue<pii,vector<pii>,greater<pii> >p;
     69     while(!que.empty())
     70     {
     71         int k = que.front();
     72         que.pop();
     73         while(!p.empty())
     74             p.pop();
     75         int len = belong[k].size();
     76         for(int i=0; i<len; i++)
     77         {
     78             if(dist[belong[k][i]] < 0x3f3f3f3f)
     79                 p.push(pii(dist[belong[k][i]],belong[k][i]));
     80         }
     81         while(!p.empty())
     82         {
     83             pii t = p.top();
     84             p.pop();
     85             if(vis[t.second])
     86                 continue;
     87             vis[t.second] = 1;
     88             for(int i=head[0][t.second]; i; i=node[0][i].next)
     89             {
     90                 if(dist[t.second] + node[0][i].val < dist[node[0][i].y])
     91                 {
     92                     dist[node[0][i].y] = dist[t.second] + node[0][i].val;
     93                     p.push(pii(dist[t.second] + node[0][i].val,node[0][i].y));
     94                 }
     95             }
     96             for(int i=head[1][t.second]; i; i=node[1][i].next)
     97             {
     98                 dist[node[1][i].y] = min(dist[node[1][i].y],dist[t.second]+node[1][i].val);
     99             }
    100         }
    101         for(int i=0; i<len; i++)
    102         {
    103             for(int j=head[1][belong[k][i]]; j; j=node[1][j].next)
    104             {
    105                 if(--ind[cn[node[1][j].y]] == 0)
    106                     que.push(cn[node[1][j].y]);
    107             }
    108         }
    109     }
    110 }
    111 
    112 int main()
    113 {
    114     cnt[0] = cnt[1] = 0;
    115     scanf("%d%d%d%d",&t,&r,&p,&s);
    116     for(int i=1; i<=t; i++)
    117         belong[i].clear();
    118     for(int i=1; i<=r; i++)
    119     {
    120         int u,v,k;
    121         scanf("%d%d%d",&u,&v,&k);
    122         add(u,v,k,0);
    123         add(v,u,k,0);
    124     }
    125 
    126     for(int i=1; i<=p; i++)
    127     {
    128         int u,v,k;
    129         scanf("%d%d%d",&u,&v,&k);
    130         add(u,v,k,1);
    131     }
    132     tot = 0;
    133     for(int i=1; i<=t; i++)
    134     {
    135         if(!cn[i])
    136         {
    137             tot++;
    138             dfs(i);
    139         }
    140     }
    141 
    142 
    143     for(int i=1; i<=cnt[1]; i++)
    144     {
    145         ind[cn[node[1][i].y]]++;
    146     }
    147     solve(s);
    148     for(int i=1; i<=t; i++)
    149     {
    150         if(dist[i] == 0x3f3f3f3f)
    151             printf("NO PATH
    ");
    152         else
    153             printf("%d
    ",dist[i]);
    154     }
    155 }
    View Code
     
  • 相关阅读:
    Android jni/ndk编程五:jni异常处理
    Android jni/ndk编程四:jni引用类型
    Android jni/ndk编程三:native访问java
    Android jni/ndk编程二:jni数据类型转换(primitive,String,array)
    Android jni/ndk编程一:jni初级认识与实战体验
    C++静态库与动态库
    Android——NativeActivity
    Eclipse IDE for C/C++ Developers和MinGW安装配置C/C++开发学习环境详解
    Android OkHttp3简介和使用详解*
    Android MVP 设计模式*
  • 原文地址:https://www.cnblogs.com/iwannabe/p/10673698.html
Copyright © 2020-2023  润新知