1. 程式人生 > >hihocoder 1689 推斷大小關係 並查集+dfs

hihocoder 1689 推斷大小關係 並查集+dfs

#1689 : 推斷大小關係

時間限制:20000ms

單點時限:2000ms

記憶體限制:256MB

描述

有N個整數A1, A2, ... AN,現在我們知道M條關於這N個整數的資訊。每條資訊是:

Ai < Aj 或者 Ai = Aj  

小Hi希望你能從第一條資訊開始依次逐條處理這些資訊。一旦能推斷出A1和AN的大小關係就立即停止。  

輸出在處理第幾條時第一次推斷出A1和AN的關係。如果處理完全部M條資訊還是不知道A1和AN的大小關係,輸出-1。  

保證M條資訊是沒有矛盾的。

輸入

第一行包含兩個整數N和M。  

以下M行每行包含一條資訊Ai < Aj 或者 Ai = Aj。  

對於30%的資料,1 ≤ N ≤ 1000, 1 ≤ M ≤ 10000  

對於100%的資料,1 ≤ N ≤ 100000, 1 ≤ N ≤ 1000000

輸出

一個整數表示答案。

樣例輸入

5 8  
A1 < A3  
A3 < A2  
A3 < A4  
A5 < A2  
A1 < A4  
A1 < A2  
A5 < A1  
A5 < A3

樣例輸出

7

思路:從1和n號點開始擴張,如果1號擴張到 n號或者與n相等的點(並查集判斷),則認為關係明確,反之亦然。如果1號擴張的點到n的地盤,擴張終止。擴張路徑只使用一次,每次使用後,刪除該邊。

#include <iostream>
#include<bits/stdc++.h>

using namespace std;

const int MX=1e5+100;
int n,m,par[MX],rk[MX],label[MX];
vector<int> g[MX];
void init(int n)
{
    for(int i=0;i<=n;i++) par[i]=i,rk[i]=0,g[i].clear();
    memset(label,0,sizeof(label));
}
int f(int x)
{
    if(par[x]==x) return x;
    return par[x]=f(par[x]);
}
void unite(int x,int y)
{
    x=f(x);
    y=f(y);
    if(x==y) return ;
    if(rk[x]<rk[y]) par[x]=y;
    else
    {
        par[y]=x;
        if(rk[x]==rk[y]) rk[x]++;
    }
}
bool dfs(int u,int num)
{

    if(num==1&&f(u)==f(n) ) return true;
    if(num==n&&f(u)==f(1) ) return true;
    if(label[u]!=0&&label[u]!=num) return false;
    label[u]=num;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(label[v]!=num) if(dfs(v,num)) return true;
    }
    g[u].clear();
    return false;
}
int main()
{
    while(cin>>n>>m)
    {
        init(n);
        label[1]=1;label[n]=n;
        int ans=-1;
        for(int i=0;i<m;i++)
        {
            int x,y;
            char c;
            scanf("\nA%d %c A%d",&x,&c,&y);
            if(ans>0) continue;
            if(c=='=')
            {
                unite(x,y);
                g[x].push_back(y);
                if(label[x]==1 ||label[x]==n)
                    if(dfs(x,label[x])) ans=i+1;


                g[y].push_back(x);
                if(label[y]==1||label[y]==n)
                    if(dfs(y,label[y])) ans=i+1;
            }
            else
            {
                g[x].push_back(y);
                if( label[x] == 1 || label[x]==n)
                    if(dfs(x,label[x])) ans=i+1;
            }

        }
        cout<<ans<<endl;
    }
    return 0;
}