Hihocoder Chen 1689: inferring size relation (dichotomy)

Time limit: 20000ms
Single point time limit: 2000ms
Memory limit: 256MB

describe

There are N integers A1, A2, ... AN, now we know M pieces of information about these N integers. Each message is:

Ai < AJ or Ai = Aj  

Little Hi wants you to start with the first message and process it one by one. Once the size relationship between A1 and AN can be inferred, it stops immediately.  

The output infers the relationship between A1 and AN for the first time when processing article. If you do not know the size relationship between A1 and AN after processing all M pieces of information, output - 1.  

Ensure that there is no contradiction in the M information.

input

The first line contains two integers, N and M.  

Each of the following M lines contains a message Ai < AJ or Ai = Aj.  

For 30% data, 1 ≤ N ≤ 1000, 1 ≤ M ≤ 10000

For 100% data, 1 ≤ N ≤ 100000, 1 ≤ N ≤ 1000000

output

An integer represents the answer.

sample input
5 8  
A1 < A3  
A3 < A2  
A3 < A4  
A5 < A2  
A1 < A4  
A1 < A2  
A5 < A1  
A5 < A3
sample output
7
Idea: dichotomy enumeration answers.

#include<bits/stdc++.h>
using namespace std;
const int MAX=3e6;
struct lenka
{
    int to,index,tp,next;
}ed[MAX];
int head[MAX],tot=0;
void add(int x,int y,int z,int index)
{
    ed[tot].index=index;
    ed[tot].to=y;
    ed[tot].tp=z;
    ed[tot].next=head[x];
    head[x]=tot++;
}
int n,v[MAX];
int dfs(int k,int tp,int mid)//tp is the size of K relative to 1: - 1 is k < 1,0 is k=1,1 is greater than k > 1
{
    v[k]=1;
    if(k==n)return 1;
    for(int i=head[k];i!=-1;i=ed[i].next)
    {
        int nex=ed[i].to;
        if(v[nex]||ed[i].index>mid)continue;
        if(ed[i].tp==1&&tp!=-1&&dfs(nex,1,mid))return 1;
        if(ed[i].tp==0&& dfs(nex,tp,mid))return 1;
        if(ed[i].tp==-1&&tp!=1&&dfs(nex,-1,mid))return 1;
    }
    return 0;
}
int main()
{
    int m;
    scanf("%d%d ",&n,&m);
    memset(head,-1,sizeof head);
    for(int i=1;i<=m;i++)
    {
        int a,b;		    //Very speechless for input
        getchar();		    //char x[5],op[5],y[5];
        scanf("%d ", &a);	//scanf("%s%s%s",x,op,y)
        char s[2];		    //a=x[1]-'0';
        scanf("%s ", s);	//b=y[1]-'0';
        getchar();		    //Input infinite WA in this way
        scanf("%d ", &b);
        if(a==b)continue;
        if(s[0]=='<')
        {
            add(a,b,1,i); 	//b>a tp=1;
            add(b,a,-1,i);	//a<b tp=-1;
        }
        else
        {
            add(a,b,0,i);	//a=b,tp=0;
            add(b,a,0,i);	//a=b,tp=0;
        }
    }
    int l=1,r=m,ans=-1;
    while(r>=l)
    {
        int mid=(r+l)/2;
        memset(v,0,sizeof v);
        if(dfs(1,0,mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    if(n==1)ans=0;
    cout<<ans<<endl;
    return 0;
}




Posted on Mon, 04 May 2020 22:08:05 -0400 by mrausch