1. 程式人生 > >洛谷P1262+Tarjan縮點

洛谷P1262+Tarjan縮點

本題是個有關Tarjan的題。
首先我們來預習(溫習)一下tarjan縮點:SCC是相互可達,先跑Tarjan然後建個新圖。
洛谷板子:P3387

Code:

#include<iostream>
#include<cstdio>
#include<stack>
#include<queue>
#include<cstring>
#define INF 0x3f3f3f3f
#define ll long long
#define maxn 100001
using namespace std;
struct Edge{
    int nxt,to,dis;
}edge[maxn];
int n,m,low[maxn],dfn[maxn],a[maxn],tot[maxn],ans,num_edge,qaq[maxn],qwq[maxn],head[maxn],cnt,sccnum[maxn],vis[maxn],dis[maxn],scc_cnt; stack<int> s; inline void addedge(int from,int to){ edge[++num_edge].nxt=head[from]; edge[num_edge].to=to; head[from]=num_edge; } void tarjan(int x){ dfn[x]
=low[x]=++cnt; s.push(x); for(int i=head[x];i;i=edge[i].nxt){ int y=edge[i].to; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); } else if(!sccnum[y]){ low[x]=min(dfn[y],low[x]); } } if(low[x]==dfn[x]){ scc_cnt
++; for(;;){ //num[scc_cnt]++; int y=s.top(); tot[scc_cnt]+=a[y]; s.pop(); sccnum[y]=scc_cnt; if(y==x) break; } } } inline void spfa(int s){ queue<int> q; memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis)); vis[s]=1; dis[s]=tot[s]; q.push(s); while(!q.empty()){ int x=q.front(); q.pop(); vis[x]=0; for(int i=head[x];i;i=edge[i].nxt){ int y=edge[i].to; if(dis[y]<dis[x]+tot[y]){ dis[y]=dis[x]+tot[y]; if(vis[y]==0){ q.push(y); vis[y]=1; } } } } for(int i=1;i<=scc_cnt;i++){ ans=max(ans,dis[i]); } } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=m;i++){ int x,y; cin>>x>>y; addedge(x,y); qwq[i]=x; qaq[i]=y; } for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } memset(edge,0,sizeof(edge)); memset(head,0,sizeof(head)); num_edge=0; for(int i=1;i<=m;i++){ if(sccnum[qwq[i]]!=sccnum[qaq[i]]){ addedge(sccnum[qwq[i]],sccnum[qaq[i]]); } } for(int i=1;i<=scc_cnt;i++){ spfa(i); } cout<<ans; return 0; }

我們再考慮間諜網路這個題。
統計一下入度,沒了。
Code:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<stack>
#include<cmath>
#define ll long long
#define maxn 100001
#define INF 0x3f3f3f3f
using namespace std;
struct Edge{
    int nxt,to,dis;
}edge[maxn];
int n,m,low[maxn],dfn[maxn],rd[maxn],a[maxn],tot[maxn],ans,num_edge,qaq[maxn],qwq[maxn],head[maxn],cnt,sccnum[maxn],vis[maxn],dis[maxn],scc_cnt;
stack<int> s;
inline void addedge(int from,int to){
    edge[++num_edge].nxt=head[from];
    edge[num_edge].to=to;
    head[from]=num_edge;
}
void tarjan(int x){
    dfn[x]=low[x]=++cnt;
    s.push(x);
    for(int i=head[x];i;i=edge[i].nxt){
        int y=edge[i].to;
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(!sccnum[y]){
            low[x]=min(dfn[y],low[x]);
        }
    }
    if(low[x]==dfn[x]){
        scc_cnt++;
        for(;;){
            //num[scc_cnt]++;
            int y=s.top();
           // tot[scc_cnt]+=a[y];
            tot[scc_cnt]=min(tot[scc_cnt],a[y]);
            s.pop();
            sccnum[y]=scc_cnt;
            if(y==x) break;
        }
    }
}
int main(){
    memset(a,INF,sizeof(a));
    memset(tot,INF,sizeof(tot));
    int p,r;
    cin>>n>>p;
    for(int i=1;i<=p;i++){
       // int x,y;
        //cin>>x>>y;
        //addedge(x,y);
        //qwq[i]=x;
        //qaq[i]=y;
        int x,y;
        cin>>x>>y;
        a[x]=y;
    }
    cin>>r;
    for(int i=1;i<=r;i++){
        int x,y;
        cin>>x>>y;
        addedge(x,y);
    //    qwq[i]=x;
    //    qaq[i]=y;
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]&&a[i]!=INF) tarjan(i);
    }
  //  memset(edge,0,sizeof(edge));
  //  memset(head,0,sizeof(head));
   // num_edge=0;
    for(int i=1;i<=n;i++){
        if(!dfn[i]){
            cout<<"NO"<<endl;
            cout<<i<<endl;
            return 0;
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=head[i];j;j=edge[j].nxt){
            if(sccnum[i]!=sccnum[edge[j].to]){
            rd[sccnum[edge[j].to]]++; 
        }
    }
   for(int i=1;i<=scc_cnt;i++){
       if(!rd[i]){
           ans+=tot[i];
       }
   }
   cout<<"YES"<<endl;
    cout<<ans<<endl;
    return 0;
}