P2835 刻錄光盤
洛谷—— P2835 刻錄光盤
題目描述
在JSOI2005夏令營快要結束的時候,很多營員提出來要把整個夏令營期間的資料刻錄成一張光盤給大家,以便大家回去後繼續學習。組委會覺得這個主意不錯!可是組委會一時沒有足夠的空光盤,沒法保證每個人都能拿到刻錄上資料的光盤,又來不及去買了,怎麽辦呢?!
組委會把這個難題交給了LHC,LHC分析了一下所有營員的地域關系,發現有些營員是一個城市的,其實他們只需要一張就可以了,因為一個人拿到光盤後,其他人可以帶著U盤之類的東西去拷貝啊!
可是,LHC調查後發現,由於種種原因,有些營員並不是那麽的合作,他們願意某一些人到他那兒拷貝資料,當然也可能不願意讓另外一些人到他那兒拷貝資料,這與我們JSOI宣揚的團隊合作精神格格不入!!!
現在假設總共有N個營員(2<=N<=200),每個營員的編號為1~N。LHC給每個人發了一張調查表,讓每個營員填上自己願意讓哪些人到他那兒拷貝資料。當然,如果A願意把資料拷貝給B,而B又願意把資料拷貝給C,則一旦A獲得了資料,則B,C都會獲得資料。
現在,請你編寫一個程序,根據回收上來的調查表,幫助LHC計算出組委會至少要刻錄多少張光盤,才能保證所有營員回去後都能得到夏令營資料?
輸入輸出格式
輸入格式:
先是一個數N,接下來的N行,分別表示各個營員願意把自己獲得的資料拷貝給其他哪些營員。即輸入數據的第i+1行表示第i個營員願意把資料拷貝給那些營員的編號,以一個0結束。如果一個營員不願意拷貝資料給任何人,則相應的行只有1個0,一行中的若幹數之間用一個空格隔開。
輸出格式:
一個正整數,表示最少要刻錄的光盤數。
輸入輸出樣例
輸入樣例#1:5 2 3 4 0 4 5 0 0 0 1 0輸出樣例#1:
1
代碼:
智障啊。。。。
mdzz用讀入優化做第六個點超時,不用讀入優化就過了,過了。。。。
#include<stack> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #defineN 29999//在洛谷上交的時候,必須的大一點,不然RE using namespace std; stack<int>s; struct Edge { int from,to,next; }edge[N]; bool vis[N]; int n,x,y,tot,sum,ans,tim; int in[N],dfn[N],low[N],head[N],belong[N]; void add(int x,int y) { tot++; edge[tot].to=y; edge[tot].next=head[x]; head[x]=tot; } int tarjan(int now) { dfn[now]=low[now]=++tim; vis[now]=true;s.push(now); int j; for(int i=head[now];i;i=edge[i].next) { j=edge[i].to; if(vis[j]) low[now]=min(dfn[j],low[now]); else if(!dfn[j]) tarjan(j),low[now]=min(low[now],low[j]); } if(low[now]==dfn[now]) { sum++; do { j=s.top(); s.pop(); vis[j]=0; belong[j]=sum; }while(j!=now); } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&x); while(x) { add(i,x); scanf("%d",&x); } } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) { for(int j=head[i];j;j=edge[j].next) { y=edge[j].to; if(belong[i]!=belong[y]) in[belong[y]]=1; } } for(int i=1;i<=sum;i++) if(!in[i]) ans++; printf("%d",ans); return 0; }
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 2010 using namespace std; bool vis[N]; int n,a,ans,sum,tat,top,tim; int in[N],head[N],dfn[N],low[N],stack[N],col[N]; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } struct Edge { int from,next,to; }edge[N]; inline int add(int x,int y) { tat++; edge[tat].to=y; edge[tat].next=head[x]; head[x]=tat; } inline void tarjan(int now) { dfn[now]=low[now]=++tim; stack[++top]=now;vis[now]=true; int t; for(int i=head[now];i;i=edge[i].next) { t=edge[i].to; if(vis[t]) low[now]=min(low[now],dfn[t]); else if(!dfn[t]) tarjan(t),low[now]=min(low[now],low[t]); } if(low[now]==dfn[now]) { sum++;col[now]=sum; for(;stack[top]!=now;top--) { col[stack[top]]=sum; vis[stack[top]]=false; } vis[now]=false; top--; } } inline void shrink_point() { for(int i=1;i<=n;i++) for(int j=head[i];j;j=edge[j].next) if(col[i]!=col[edge[j].to]) { in[col[edge[j].to]]=1; } } int main() { n=read(); for(int i=1;i<=n;i++) { while(1) { a=read(); if(a==0) break; add(i,a); } } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); shrink_point(); for(int i=1;i<=sum;i++) if(in[i]==0) ans++; printf("%d",ans); return 0; }
錯誤:in[col[edge[j].to]]++;我最開始是這樣打的,但是這樣在codevs上最後一個點不過,改成in[col[edge[j].to]]=1就過了!!!!迷啊?!哪位大佬可以跟我說說。。。
但這樣在洛谷上不過,我們需要把數據範圍開大點。。。。(唉,在codevs上1000可以過,在洛谷上就必須開到30000。。。。。)
P2835 刻錄光盤