LIGHTOJ1074

来源:互联网 发布:如何找回网络密码 编辑:程序博客网 时间:2024/04/28 12:09

/********************************************

Author         :JamesQi

Created Time   :2015.6.3

File Name      :图论训练//LightOJ1074.cpp

********************************************/


#include <cstdio>

#include <cstdlib>

#include <iostream>

#include <algorithm>

#include <cstring>

#include <climits>

#include <string>

#include <vector>

#include <cmath>

#include <stack>

#include <queue>

#include <set>

#include <map>


using namespace std;


const int inf=0x3f3f3f3f;

constint maxn=220;

constint MOD=1e5+7;

typedef pair<int,int> ii;


struct Edge

{

   int v,cost;

    Edge(int _v=0,int _cost=0)

    {

        v=_v;

        cost=_cost;

    }

};


vector<Edge> E[maxn];

void addedge(int u,int v,int w)

{

    E[u].push_back(Edge(v,w));

}

bool vis[maxn];

int dist[maxn];

int cnt[maxn];


bool cir[maxn];



void dfs(int u)

{

    cir[u]=true;

   for (int i=0;i<E[u].size();i++)

    {

       if (!cir[E[u][i].v])

            dfs(E[u][i].v);

    }//由负环可达的点全部标记起来

}


void spfa(int st,int n)

{

    memset(vis,false,sizeof vis);

    memset(dist,inf,sizeof dist);

    memset(cnt,0,sizeof cnt);

    memset(cir,false,sizeof cir);

    vis[st]=true;

    dist[st]=0;

    cnt[st]=1;

    queue<int> que;

   while(!que.empty()) que.pop();

    que.push(st);

   while(!que.empty())

    {

       int u=que.front();

        que.pop();

        vis[u]=false;

       for (int i=0;i<E[u].size();i++)

        {

           int v=E[u][i].v;

           int cost=E[u][i].cost;

           if (cir[v]) continue;//负环上的点或者说是负环可达的点

           if (dist[v]>dist[u]+cost)

            {

                dist[v]=dist[u]+cost;

               if (!vis[v])

                {

                    vis[v]=true;

                    que.push(v);

                    cnt[v]++;

                   if (cnt[v]>n)

                        dfs(v);//出现负环就开始做标记

                }

            }

        }

    }

}

int a[maxn];

int main()

{

    freopen("in.txt","r",stdin);

    //freopen("out.txt","w",stdout);

   int T;

    scanf("%d",&T);

   int icase=0;

   while(T--)

    {

        icase++;

       int n;

        scanf("%d",&n);

       for (int i=1;i<=n;i++)

            scanf("%d",&a[i]);

       int m,u,v;

       for (int i=1;i<=n;i++)

            E[i].clear();

        scanf("%d",&m);

       while(m--)

        {

            scanf("%d%d",&u,&v);

            addedge(u,v,(a[v]-a[u])*(a[v]-a[u])*(a[v]-a[u]));

        }

        spfa(1,n);

        printf("Case %d:\n",icase);

        scanf("%d",&m);

       while(m--)

        {

            scanf("%d",&u);

           if (cir[u] || dist[u]<3 || dist[u]==inf)

                printf("?\n");

           else printf("%d\n",dist[u]);

        }

    }

   return 0;

}

/*

PS:由于一开始题目没告诉我边的数目,

我就只开了10000,结果wa了三发,改成1e6就过了;ORZ

#include <cstdio>

#include <cstdlib>

#include <iostream>

#include <algorithm>

#include <cstring>

#include <climits>

#include <string>

#include <vector>

#include <cmath>

#include <stack>

#include <queue>

#include <set>

#include <map>


using namespace std;


const int inf=0x3f3f3f3f;

const int maxn=1000000;

const int MOD=1e5+7;

int head[maxn],pnt[maxn],cost[maxn],nxt[maxn];

int dist[maxn];

bool cir[maxn];//标记负环

int cnt;


void addedge(int u,int v,int w)

{

    pnt[cnt]=v;

    cost[cnt]=w;

    nxt[cnt]=head[u];

    head[u]=cnt++;

}


void dfs(int u)

{

    cir[u]=true;

    for (int i=head[u];i!=-1;i=nxt[i])

    {

        if (!cir[pnt[i]])

            dfs(pnt[i]);

    }

}


void SPFA(int start,int n)

{

    bool vis[maxn];

    int in[maxn];

    queue<int> que;

    while(!que.empty()) que.pop();

    memset(vis,false,sizeof vis);

    memset(in,0,sizeof in);

    memset(dist,inf,sizeof dist);

    memset(cir,false,sizeof cir);

    in[start]=1;

    vis[start]=true;

    dist[start]=0;

    que.push(start);

    while(!que.empty())

    {

        int u=que.front();

        que.pop();

        vis[u]=false;

        for (int i=head[u];i!=-1;i=nxt[i])

        {

            int v=pnt[i];

            if (cir[v]) continue;

            if (dist[v]>dist[u]+cost[i])

            {

                dist[v]=dist[u]+cost[i];

                if (!vis[v])

                {

                    vis[v]=true;

                    que.push(v);

                    in[v]++;

                    if (in[v]>n)

                        dfs(v);

                }

            }

        }

    }

}



int main()

{

    //freopen("in.txt","r",stdin);

    //freopen("out.txt","w",stdout);

    int T;

    int iCase=0;

    //cin>>T;

    scanf("%d",&T);

    int a[1000];

    while(T--)

    {

        //cout<<"T="<<T<<endl;

        memset(head,-1,sizeof head);

        cnt=0;

        iCase++;

        int n;

        scanf("%d",&n);

        for (int i=1;i<=n;i++)

            //cin>>a[i];

            scanf("%d",&a[i]);

        //for (int i=1;i<=n;i++)

        //  cout<<a[i]<<" ";

        //cout<<endl;

        int m;

        //cin>>m;

        scanf("%d",&m);

        int u,v;

        for (int i=1;i<=m;i++)

        {

            //cin>>u>>v;

            scanf("%d%d",&u,&v);

            addedge(u,v,(a[v]-a[u])*(a[v]-a[u])*(a[v]-a[u]));

        }

        SPFA(1,n);

        //cout<<"Case "<<icase<<":"<<endl;

        printf("Case %d:\n",iCase);

        //cin>>m;

        scanf("%d",&m);

        while(m--)

        {

            //cin>>u;

            scanf("%d",&u);

            if (cir[u] || dist[u]<3 || dist[u]==inf)

                printf("?\n");

            else printf("%d\n",dist[u]);

        }

    }

    return 0;

}

*/


0 0