解题:USACO15JAN Grass Cownoisseur

解题

首先缩点没啥可说的,然后考虑枚举这次逆行的边。具体来说在正常的图和反图上各跑一次最长路,然后注意减掉起点的贡献,用拓扑排序实现(我这里瞎写了个Bellman_Ford,其实在DAG上这好像和拓扑排序的复杂度是一样的=。=)

一个细节:注意可能整个图是个强连通分量,所以答案初始是起点所在的强联通分量的大小

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std; 
 6 const int N=100005;
 7 int dfn[N],low[N],col[N],stk[N],ins[N],inq[N],siz[N],dis[2][N];
 8 int p[N],noww[N],goal[N],P[N][2],Noww[N][2],Goal[N][2]; 
 9 int n,m,c,t1,t2,cnt,cnt0,cnt1,tot,top,ans; 
10 queue<int> qs;
11 void link(int f,int t) 
12 { 
13     noww[++cnt]=p[f]; 
14     goal[cnt]=t,p[f]=cnt; 
15 } 
16 void relink(int f,int t)
17 {
18     Noww[++cnt0][0]=P[f][0];
19     Goal[cnt0][0]=t,P[f][0]=cnt0;
20     Noww[++cnt1][1]=P[t][1];
21     Goal[cnt1][1]=f,P[t][1]=cnt1;
22 }
23 void Tarjan_SCC(int nde)
24 {
25     dfn[nde]=low[nde]=++tot;
26     stk[++top]=nde,ins[nde]=true;
27     for(int i=p[nde];i;i=noww[i])
28         if(!dfn[goal[i]]) 
29             Tarjan_SCC(goal[i]),low[nde]=min(low[nde],low[goal[i]]);
30         else if(ins[goal[i]])
31             low[nde]=min(low[nde],low[goal[i]]);
32     if(dfn[nde]==low[nde])
33     {
34         c++; int tmp;
35         do
36         {
37             tmp=stk[top--];
38             ins[tmp]=false;
39             col[tmp]=c,siz[c]++;
40         }while(nde!=tmp);
41     }
42 }
43 void Bellman_Ford(int s,int t)
44 {
45     memset(dis[t],0xc0,sizeof dis[t]);
46     dis[t][s]=siz[s],qs.push(s),inq[s]=true;
47     while(!qs.empty())
48     {
49         int tn=qs.front(); 
50         qs.pop(),inq[tn]=false;
51         for(int i=P[tn][t];i;i=Noww[i][t])
52             if(dis[t][Goal[i][t]]<dis[t][tn]+siz[Goal[i][t]])
53             {
54                 dis[t][Goal[i][t]]=dis[t][tn]+siz[Goal[i][t]];
55                 if(!inq[Goal[i][t]]) 
56                     qs.push(Goal[i][t]),inq[Goal[i][t]]=true;
57             }
58     }
59 }
60 int main() 
61 { 
62     scanf("%d%d",&n,&m); 
63     for(int i=1;i<=m;i++) 
64         scanf("%d%d",&t1,&t2),link(t1,t2);
65     for(int i=1;i<=n;i++)
66         if(!dfn[i]) Tarjan_SCC(i);
67     for(int i=1;i<=n;i++)
68         for(int j=p[i];j;j=noww[j])
69             if(col[i]!=col[goal[j]])
70                 relink(col[i],col[goal[j]]); 
71     Bellman_Ford(col[1],0),Bellman_Ford(col[1],1),ans=siz[col[1]];
72     for(int i=1;i<=c;i++)
73         for(int j=P[i][1];j;j=Noww[j][1])
74             ans=max(ans,dis[0][i]+dis[1][Goal[j][1]]-siz[col[1]]);
75     printf("%d",ans);
76     return 0;
77 }
View Code

 

posted @ 2018-10-23 22:06  Speranza_Leaf  阅读(124)  评论(0)    收藏  举报