1. 程式人生 > >SIMPPOLY 2017 ACM-ICPC Asia Amritapuri Regional Contest H DAG圖中判斷是否有一條鏈包含所有的點。

SIMPPOLY 2017 ACM-ICPC Asia Amritapuri Regional Contest H DAG圖中判斷是否有一條鏈包含所有的點。

思路: 二分 ans 然後judge  judge 的時候先縮點然後生成一個DAG圖,然後跑出一個topo序列,然後判斷相鄰的兩個點之間是否有連邊沒有則不滿足。

程式碼:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int inf =0x3f3f3f3f;
typedef pair<int ,int > pii;
const int N = 100005;

int n,m;
vector< pii >ve1[N],ve[N];
int outde[N];
int inde[N];
int ins[N];
int st[N];
int low[N],belong[N],dfn[N];
int top;
int Index;
int scc;
set<int >se[N];

void tarjan(int u)
{
    int v;
    low[u]=dfn[u]=++Index;
    st[top++]=u;
    ins[u]=1;
    for(int i=0;i<ve[u].size();i++)
    {
        v=ve[u][i].first;
        if(!dfn[v])
        {
            tarjan(v);
            if(low[v]<low[u]) low[u]=low[v];
        }
        else if(ins[v]&&dfn[v]<low[u]) low[u]=dfn[v];
    }
    if(low[u]==dfn[u])
    {
        scc++;
        //printf("*** u %d %d\n",u,scc);
        do
        {
            v=st[--top];
            ins[v]=0;
            belong[v]=scc;
        }while(v!=u);
    }
}

void init()
{
    for(int i=1;i<=n+2;i++) ve[i].clear();
    for(int i=0;i<=n+2;i++)
    {
        ins[i]=outde[i]=st[i]=belong[i]=low[i]=dfn[i]=inde[i]=0;
    }
    top=Index=scc=0;
}

int jud(int mid)
{
    init();
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<ve1[i].size();j++)
        {
            if(ve1[i][j].second<=mid)
            {
                ve[i].push_back(ve1[i][j]);
               // printf("******* %d %d %d\n",i,ve1[i][j].first,ve1[i][j].second);
               // printf("******* %d %d %d\n",i,ve[i][j].first,ve[i][j].second);
            }
        }
    }

    int uu,vv,u,v;
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i]) tarjan(i);
    }
    if(scc==1) return 1;

    for(int i=0;i<=n+2;i++) se[i].clear();
    for(int i=0;i<=n+2;i++) inde[i]=0;

    for(int i=1;i<=n;i++)
    {
        uu=i;
        for(int j=0;j<ve[i].size();j++)
        {
            vv=ve[i][j].first;
            //printf("**&&&&& uv %d %d\n",uu,vv);
            u=belong[uu];
            v=belong[vv];
            if(u==v) continue;
            if(se[u].count(v)==0)
            {
                se[u].insert(v);
                //printf("hHHHHh %d %d\n",u,v);
                inde[v]++;
            }
        }
    }
    /*
    for(int i=1;i<=scc;i++)
    {
        for(set<int >::iterator it=se[i].begin();it!=se[i].end();it++)
        {
            printf("** %d %d\n",i,*it);
        }
    }
    */

    vector< int >topo;

    int f=0;
    queue< int >q;
    for(int i=1;i<=scc;i++)
    {
        if(inde[i]==0)
        {
            q.push(i);
        }
    }

    while(!q.empty())
    {
        u=q.front(); q.pop();
        topo.push_back(u);
        for(set<int >::iterator it=se[u].begin();it!=se[u].end();it++)
        {
            v=*it;
            inde[v]--;
            if(inde[v]==0)
            {
                q.push(v);
            }
        }
    }

    if(topo.size()!=scc) return 0;
    if(topo.size()<=1) return 1;

    f=0;
    for(int i=0;i<topo.size()-1;i++)
    {
        u=topo[i]; v=topo[i+1];
        if(se[u].count(v)==0)
        {
            f=1; break;
        }
    }

    if(f) return 0;
    return 1;
}

void init1()
{
    for(int i=0;i<=n+2;i++)
    {
        ve[i].clear();
        ve1[i].clear();
    }
    memset(st,0,sizeof(st));
    memset(ins,0,sizeof(ins));
    memset(outde,0,sizeof(outde));
    memset(inde,0,sizeof(inde));
    memset(low,0,sizeof(low));
    memset(belong,0,sizeof(belong));
    memset(dfn,0,sizeof(dfn));
    top=Index=scc=0;
}

int main()
{
    int u,v,w;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&n,&m);
        init1();

        int L,R;
        R=-1;
        L=inf;
        for(int i=1;i<=m;i++)
        {
            scanf("%d %d %d",&u,&v,&w);
            ve1[u].push_back(pii(v,w));
            L=min(L,w);
            R=max(R,w);
        }

        int mid;
        int ans=-1;
        while(L<=R)
        {
            mid=(L+R)>>1;
            if(jud(mid))
            {
                ans=mid;
                R=mid-1;
            }
            else L=mid+1;
        }

        if(ans==-1)
        {
            printf("Impossible\n");
        }
        else printf("%d\n",ans);

    }
    return 0;
}

/*

5
4 3
1 2 1
2 3 1
2 4 1

*/