ACdream 1083 人民城管爱人民

 拓扑排序,然后从终点开始递推。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
#include<ctime>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0);
void File()
{
    freopen("D:\in.txt","r",stdin);
    freopen("D:\out.txt","w",stdout);
}

const int INF=0x7FFFFFFF;
int T,n,m;
struct Edge {int u,v,w,nx; } e[100010];
int sz,h[10010],r[10010];
struct X { int order,id; } p[10010];
int dis[10010][2];

void add(int a,int b,int c)
{
    e[sz].u=a; e[sz].v=b; e[sz].w=c; e[sz].nx=h[a]; h[a]=sz++;
}

bool cmp(X a,X b){ return a.order>b.order; }

bool top()
{
    queue<int>Q; sz=0;
    for(int i=0;i<n;i++) if(r[i]==0) Q.push(i);

    while(!Q.empty())
    {
        int t=Q.front(); Q.pop(); sz++; p[sz].order=sz; p[sz].id=t;
        for(int i=h[t];i!=-1;i=e[i].nx)
            { r[e[i].v]--; if(r[e[i].v]==0) Q.push(e[i].v); }
    }
}

int main()
{
    scanf("%d",&T); while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(h,-1,sizeof h);
        memset(r,sz=0,sizeof r);
        for(int i=1;i<=m;i++)
        {
            int u,v,w; scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); r[v]++;
        }
        top();

        for(int i=0;i<=n;i++) dis[i][0]=dis[i][1]=INF;

        for(int i=n;i>=1;i--)
        {
            int id=p[i].id;
            if(id==n-1) { dis[id][1]=dis[id][0]=0; continue;}
            for(int j=h[id];j!=-1;j=e[j].nx)
            {
                if(dis[e[j].v][0]==INF) continue;
                dis[id][0]=min(dis[id][0],dis[e[j].v][0]+e[j].w);
            }

            int x1=INF,x2=INF;

            for(int j=h[id];j!=-1;j=e[j].nx)
            {
                if(dis[e[j].v][1]==INF) continue;
                x1=min(x1,dis[e[j].v][1]+e[j].w);
            }

            bool flag=0;
            for(int j=h[id];j!=-1;j=e[j].nx)
            {

                if(dis[e[j].v][0]==INF) continue;
                if(flag==0&&dis[e[j].v][0]+e[j].w==dis[id][0]) { flag=1; continue; }
                x2=min(x2,dis[e[j].v][0]+e[j].w);
            }

            dis[id][1]=max(x1,x2);
        }

        if(dis[0][1]==INF||dis[0][0]==INF) printf("-1
");
        else printf("%d
",dis[0][1]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5782060.html