1. 程式人生 > >【洛谷P3119】[USACO15JAN]草鑒定Grass Cownoisseur

【洛谷P3119】[USACO15JAN]草鑒定Grass Cownoisseur

color 影響 縮點 col targe vector () 如果 tex

草鑒定Grass Cownoisseur

題目鏈接

約翰有n塊草場,編號1到n,這些草場由若幹條單行道相連。奶牛貝西是美味牧草的鑒賞家,她想到達盡可能多的草場去品嘗牧草。

貝西總是從1號草場出發,最後回到1號草場。她想經過盡可能多的草場,貝西在通一個草場只吃一次草,所以一個草場可以經過多次。因為草場是單行道連接,這給貝西的品鑒工作帶來了很大的不便,貝西想偷偷逆向行走一次,但最多只能有一次逆行。問,貝西最多能吃到多少個草場的牧草。

如果沒有逆行操作和回到1的限制,我們很容易想到一種方法:

Tarjan縮點,再 記憶化搜索/拓撲排序 一遍,求出一條最長的鏈

如果加上回到1的限制:只能走一遍1所在的連通塊

再加上逆行操作,就有些復雜了,

因為只有一次逆行操作,我們可以建一個分層圖,

第一層的點和第二層的點連一條與第一層中方向相反的邊

SPFA求最長路即可

為什麽不會走除了1以外重復的點:若到達第二層後,

又走到了在第一層中走過的點,由於DAG的性質,

它是無法再走到1的,不會產生影響

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<queue>
 4 #define N 100010
 5 #define min(a,b) (a<b?a:b)
 6 int n,m,head[N],to[N],next[N],num;
7 const int ch_top=4e7+3; 8 char ch[ch_top],*now_r=ch-1,*now_w=ch-1; 9 inline int read(){ 10 while(*++now_r<0); 11 register int x=*now_r-0; 12 while(*++now_r>=0)x=x*10+*now_r-0; 13 return x; 14 } 15 struct HA{ 16 int pos,val; 17 }; 18 struct cmp{ 19 inline bool operator
()(HA a,HA b){ 20 return a.val>b.val; 21 } 22 }; 23 std::priority_queue< HA, std::vector<HA>, cmp > q; 24 int dfn[N],low[N],tot; 25 int size[N<<1],belong[N],cnt; 26 int stack[N],top; 27 bool ins[N]; 28 void Tarjan(int u){ 29 dfn[u]=low[u]=++tot; 30 stack[++top]=u; ins[u]=1; 31 for(int i=head[u];i;i=next[i]){ 32 int v=to[i]; 33 if(!dfn[v]){ 34 Tarjan(v); 35 low[u]=min(low[u],low[v]); 36 } 37 else if(ins[v]) 38 low[u]=min(low[u],dfn[v]); 39 } 40 if(dfn[u]==low[u]){ 41 belong[u]=++cnt; 42 size[cnt]=1; 43 while(stack[top]!=u){ 44 int k=stack[top]; 45 belong[k]=cnt; 46 ++size[cnt]; 47 ins[k]=0; --top; 48 } --top; ins[u]=0; 49 } 50 } 51 int Head[N<<2],Next[N<<2],To[N<<2],Num,dis[N<<1]; 52 bool inque[N<<2]; 53 int main() 54 { 55 fread(ch,1,ch_top,stdin); 56 n=read(); m=read(); 57 int x,y; 58 for(int i=1;i<=m;i++){ 59 x=read(); y=read(); 60 to[++num]=y; 61 next[num]=head[x]; 62 head[x]=num; 63 } 64 for(int i=1;i<=n;i++) 65 if(!dfn[i]) Tarjan(i); 66 for(int i=1;i<=cnt;i++) size[i+cnt]=size[i]; 67 for(int i=1;i<=n;i++) 68 for(int j=head[i];j;j=next[j]){ 69 int v=to[j]; x=belong[i],y=belong[v]; 70 if(x==y) continue; 71 To[++Num]=y; Next[Num]=Head[x]; 72 Head[x]=Num; To[++Num]=x+cnt; 73 Next[Num]=Head[y]; Head[y]=Num; 74 To[++Num]=y+cnt; 75 Next[Num]=Head[x+cnt]; 76 Head[x+cnt]=Num; 77 } 78 std::fill(dis,dis+1+cnt*2,-10000000); 79 dis[belong[1]]=0; 80 q.push((HA){belong[1],0}); 81 while(!q.empty()){ 82 int u=q.top().pos; inque[u]=0; 83 q.pop(); 84 for(int i=Head[u];i;i=Next[i]){ 85 int v=To[i]; 86 if(dis[v]>dis[u]+size[v]) continue; 87 dis[v]=dis[u]+size[v]; 88 if(!inque[v]){ 89 inque[v]=1; 90 q.push((HA){v,dis[v]}); 91 } 92 } 93 } 94 printf("%d\n",dis[belong[1]+cnt]); 95 return 0; 96 }

【洛谷P3119】[USACO15JAN]草鑒定Grass Cownoisseur