hdu 3592 World Exhibition //差分約束

刷刷水題,莫笑莫笑


#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define swap(t,a,b) (t=a,a=b,b=t)
const int E=20002;
const int V=1001;
const int INF=1<<30;
struct EDGE
{
    int link,val,next;
} edge[E];
int head[V],cnt[V],dist[V],e;
bool vis[V];
void addedge(int a,int b,int c)
{
    edge[e].link=b;
    edge[e].val=c;
    edge[e].next=head[a];
    head[a]=e++;
}
int relax(int u,int v,int c)
{
    if(dist[v]>dist[u]+c)
    {
       //求的是最大值,若求最小值,反號
        dist[v]=dist[u]+c;
        return 1;
    }
    return 0;
}
int SPFA(int src,int n)
{
    memset(vis,false,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    for(int i=1; i<=n; ++i)  dist[i]=INF;
    dist[src]=0;
    vis[src]=true;
    queue<int> q;
    q.push(src);
    ++cnt[src];
    while(!q.empty())
    {
        int u,v;
        u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            v=edge[i].link;
            if(relax(u,v,edge[i].val)==1&&!vis[v])
            {//如果不用relax函數,!VIS[V]的判斷應該寫在這
                q.push(v);
                vis[v]=true;
                if((++cnt[v])>n) return -1;//cnt[i]爲入隊列次數,用來判斷是否存在負權迴路
            }
        }
    }
    if(dist[n]==INF) return -2;
     // src與n不可達,有些題目可省!!!
    return dist[n];
    //返回src到n的最短距離,根據題意不同而改變
}
int main()
{
    int n, x, y;
    int T;
    int a, b, c;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d%d", &n, &x, &y);
        e=0;
        memset(head,-1,sizeof(head));
        for(int i = 1; i <= x; i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            //b - a <= c
            addedge(a, b, c);
        }
        for(int i = 1; i <= y; i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            //b - a >= c   a - b <= -c
            addedge(b, a, -c);
        }
        printf("%d\n",SPFA(1, n));
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章