P3573 [POI2014]RAJ-Rally

[POI2014]RAJ-Rally 

思维好题

考虑从topo序入手,枚举删点x

x之前的点在S,之后的在T

删除这个点后,剩下的路径是:S中的,T中的,S经过一条集合之间的边到T的

两遍topo排序得到diss,dist从x出发和到x结束的最长路

三种路径分别用堆维护

步骤:

把x的前驱到x的都删掉,把x在T的删掉,统计最大值

把x在S的加入,x到x的后继都加入

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define pb push_back
#define solid const auto &
#define enter cout<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
    char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}
namespace Modulo{
const int mod=998244353;
int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;}
void inc(int &x,int y){x=ad(x,y);}
int mul(int x,int y){return (ll)x*y%mod;}
void inc2(int &x,int y){x=mul(x,y);}
int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;}
}
//using namespace Modulo;
namespace Miracle{
const int N=500000+5;
const int M=1000000+5;
const int inf=0x3f3f3f3f;
int n,m;
struct node{
    int nxt,to;
}e[2*M];
int hd[2][N],cnt[2];
int du[2][N];
void add(int x,int y,int c){
    e[++cnt[c]].nxt=hd[c][x];
    e[cnt[c]].to=y;hd[c][x]=cnt[c];
    ++du[c][y];
}
int diss[N],dist[N];
int q[N],l,r;
int rk[N],id[N],df;
bool cmp(int x,int y){
    return rk[x]<rk[y];
}
void topo(int *hd,int *dis,int *du){
    l=1;r=0;
    memset(rk,0,sizeof rk);
    df=0;
    for(reg i=1;i<=n;++i){
        if(du[i]==0) {
            q[++r]=i;dis[i]=0;
        }
    }
    while(l<=r){
        int x=q[l++];
        // cout<<" xx "<<x<<endl;
        rk[x]=++df;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            // cout<<" yy "<<y<<endl;
            du[y]--;
            dis[y]=max(dis[y],dis[x]+1);
            if(du[y]==0){
                q[++r]=y;
            }
        }
    }
}
struct heap{
    priority_queue<int>q,d;
    void push(int x){q.push(x);}
    void dele(int x){d.push(x);}
    int top(){
        while(!q.empty()&&!d.empty()&&q.top()==d.top()) q.pop(),d.pop();
        if(q.size()) return q.top();
        return -inf;
    }
}q1,q2,q3;
int main(){
    rd(n);rd(m);
    int x,y;
    cnt[1]=m;
    for(reg i=1;i<=m;++i){
        rd(x);rd(y);
        add(x,y,0);add(y,x,1);
    } 
    // prt(du[0],1,n);
    // prt(hd[0],1,n);
    // cout<<cnt[0]<<endl;
    
    // enter;enter;
    topo(hd[1],diss,du[1]);
    // enter;
    topo(hd[0],dist,du[0]);
   

    // prt(diss,1,n);
    // prt(dist,1,n);
    for(reg i=1;i<=n;++i){
        id[i]=i;
        q3.push(diss[i]);
    }
    sort(id+1,id+n+1,cmp);
    int ans=inf;
    int de=0;
    for(reg p=1;p<=n;++p){
        int x=id[p];
        for(reg i=hd[1][x];i;i=e[i].nxt){
            int y=e[i].to;
            q2.dele(diss[x]+dist[y]+1);
        }
        q3.dele(diss[x]);
        int now=max(q1.top(),max(q2.top(),q3.top()));
        // cout<<" x "<<x<<" now "<<now<<endl; 
        if(ans>now){
            ans=min(ans,now);
            de=x;
        }
        q1.push(dist[x]);
        for(reg i=hd[0][x];i;i=e[i].nxt){
            int y=e[i].to;
            q2.push(dist[x]+diss[y]+1);
        }
    }
    // ot(ans);ot(de);
    ot(de);ot(ans);
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
*/

 

posted @ 2019-05-19 11:53  *Miracle*  阅读(246)  评论(0编辑  收藏  举报