• BZOJ 2200--[Usaco2011 Jan]道路和航线(最短路&拓扑排序)


    2200: [Usaco2011 Jan]道路和航线

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 1128  Solved: 414
    [Submit][Status][Discuss]

    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号城镇。

    题目链接:

        http://www.lydsy.com/JudgeOnline/problem.php?id=2200 

    Solution

      有负权边,所以不能直接dijkstra。。而spfa已经死了。。。

      但是题目保证“航线”不会出现在环里,所以如果把“道路”联结的点都缩起来就会变成一个DAG。。。

      考虑一个只由道路联结的块,此时可以直接dijkstra。。。

      DAG上就可以用拓扑排序的方法排除负权的影响,然后就没有然后了。。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<map>
    #define pa pair<int,int>
    #define LL long long
    using namespace std;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void Out(int a){
        if(a>9) Out(a/10);
        putchar(a%10+'0');
    }
    const int inf=1e9+10;
    const LL mod=1e9+7;
    const int N=2e5+50;
    int n,m1,m2,S,cnt,CNT,blo;
    int hed[N],HED[N],dis[N],bel[N],du[N];
    struct edge{
        int r,nxt,val;
    }e[N];
    void insert(int u,int v,int w){
        e[++cnt].r=v;e[cnt].nxt=hed[u];hed[u]=cnt;e[cnt].val=w;
    }
    struct EDGE{
        int r,nxt,val;
    }E[N];
    void INSERT(int u,int v,int w){
        E[++CNT].r=v;E[CNT].nxt=HED[u];HED[u]=CNT;E[CNT].val=w;
    }
    int q[N];
    priority_queue< pa ,vector< pa >,greater< pa > >PQ;
    bool vis[N];
    vector<int> ve[N];
    void dfs(int x,int c){
    	bel[x]=c;
    	ve[c].push_back(x);
    	for(int i=hed[x];i;i=e[i].nxt)
    		if(!bel[e[i].r]) dfs(e[i].r,c);
    }
    int main(){
        n=read();m1=read();m2=read();S=read();
        for(int i=1;i<=n;++i) dis[i]=inf;
        int u,v,w;
        for(int i=1;i<=m1;++i){
            u=read();v=read();w=read();
            insert(u,v,w);
            insert(v,u,w);
        }
        for(int i=1;i<=m2;++i){
            u=read();v=read();w=read();
            INSERT(u,v,w);
        }
        for(int i=1;i<=n;++i)
        	if(!bel[i]) dfs(i,++blo);
        for(int i=1;i<=n;++i)
        	for(int j=HED[i];j;j=E[j].nxt)
        		++du[bel[E[j].r]];
        int l=1,r=0,x;
        for(int i=1;i<=blo;++i)
    		if(!du[i]) q[++r]=i;
        dis[S]=0;
        while(l<=r){
        	x=q[l++];
            for(int i=0;i<ve[x].size();++i){
    			if(dis[ve[x][i]]<inf)
            		PQ.push(make_pair(dis[ve[x][i]],ve[x][i]));
    		}
            while(!PQ.empty()){
            	u=PQ.top().second;
            	w=PQ.top().first;
            	PQ.pop();
            	if(vis[u])continue;
            	else vis[u]=1;
            	for(int i=hed[u];i;i=e[i].nxt)
                	if(dis[e[i].r]>dis[u]+e[i].val){
                    	dis[e[i].r]=dis[u]+e[i].val;
                    	PQ.push(make_pair(dis[e[i].r],e[i].r));
                	}
                for(int i=HED[u];i;i=E[i].nxt)
                	if(dis[E[i].r]>dis[u]+E[i].val)
                    	dis[E[i].r]=dis[u]+E[i].val;
    		}
    		for(int i=0;i<ve[x].size();++i){
            	for(int j=HED[ve[x][i]];j;j=E[j].nxt){
            		--du[bel[E[j].r]];
            		if(!du[bel[E[j].r]]) q[++r]=bel[E[j].r];
    			}
    		}
        }
        for(int i=1;i<=n;++i){
            if(dis[i]==inf)
                printf("NO PATH
    ");
            else printf("%d
    ",dis[i]);
        }
        return 0;
    }
    

      

      

    This passage is made by Iscream-2001.

  • 相关阅读:
    Python获取秒级时间戳与毫秒级时间戳
    时间戳与时间类型转化(秒级时间戳)
    linux压缩和解压缩命令
    对于Python中@property的理解和使用
    探索性测试方法
    Linux 中 grep 命令的 12 个实践例子
    在 Linux 启动或重启时执行命令与脚本
    亲测的orabbix监控Oracle过程
    find 使用搜集
    Centos7.3-mysql5.7复制安装过程
  • 原文地址:https://www.cnblogs.com/Yuigahama/p/9671244.html
走看看 - 开发者的网上家园