關於luoguP2835 燒錄光碟 的反思

2021-08-08 04:18:34 字數 2739 閱讀 9828

mdzz這次打臉打的舒服

事情是這樣發展的

學習了圖論演算法以後,我上luogu做了燒錄光碟這一道題目,這道題目如下

題目描述

在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我翻了下題解,大家基本上都是用的floyd啊,拓撲排序的啊啥的,但這道題目比想象中的要簡單很多。

主要思想分析:

這道題目是一道圖論的練手題,我們可以用它去練習floyd啊,拓撲排序啊這些演算法。但是我們仔細讀題後可以發現,對於每乙個結點,只要有入度,就一定會有其他營員會給他傳遞資料(這是本題解思想的精髓),拿不到資料的營員就是入度為0的營員。換句話說,我們只要給所有入度為0的營員提供資料,那麼這個營員就會通過他的出度把資料傳遞出去,直到傳到出度為0的營員那裡。所以這道題目的做法就是統計所有人的入度。

哈哈,時間複雜度瞬間變成了o(n),效率大大提公升,方法也簡單了很多啊。

下面貼**

#include

using

namespace

std;

int n,sum=0;//sum用來記錄需要發出多少份資料

bool f[250];//f陣列用來記錄當前的編號為i的營員入度是否為0

以上是全域性變數宣告、標頭檔案宣告部分

void read()

}}read函式用來讀取資料、初始化陣列和變數

int count()

count函式是用來統計沒有入度的營員的個數 換句話說就是統計需要提供多少張光碟

int main()

(我已經向洛谷管理員匯報,應該馬上就會刪除)

我的方法如何推翻呢?

可以採用舉反例的方法。

我們構思一下:如果乙個有向圖裡面存在兩個強連通分量,並且每乙個強連通分量都是乙個環,那麼我統計到的所有點都是有入度的。按照的我的思路,應該返回1.但是實際上需要兩份資料。

然後我不得不用tarjan了:

1.tarjan縮點;

2.列舉相連的兩個點是否屬於同乙個強連通分量,是:入讀++;

3.統計入讀為0的強連通分量,ans++;

#include

#include

#include

#include

#include

using

namespace

std;

const

int n=250000;

int fa[n],n,a,ans=0,rd[n],head[n],k=0,tot=0,dfn[n],low[n];

struct node

edge[n*2];

void add(int u,int v)

bool vis[n];

int tim=0,sta[n],top,color_num;

int color[n];

void tarjan(int x)

else

if(vis[v]) low[x]=min(low[x],dfn[v]);

}if(dfn[x]==low[x])//染色操作

while(sta[top--]!=x);

}}int main()

}for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);

for(int i=1;i<=k;i++)

if(color[edge[i].fr]!=color[edge[i].to]) rd[color[edge[i].to]]++;

for(int i=1;i<=color_num;i++) if(!rd[i]) ans++;//判斷入讀==0

printf("%d",ans);

}//最後感謝神牛compile_error 和 zhouenji的幫助

洛谷 P2835 燒錄光碟

這道題目 先把沒有入度的點去灌水一遍 然後對於剩下的每乙個圖 他們不一定是乙個環 但是一定包含乙個環 我們只要找到乙個在環上的點,那麼就可以吧整個圖都灌水 include define ll long long using namespace std const int n 205 struct c...

洛谷P2835燒錄光碟

在jsoi2005夏令營快要結束的時候,很多營員提出來要把整個夏令營期間的資料燒錄成一張光碟給大家,以便大家回去後繼續學習。組委會覺得這個主意不錯!可是組委會一時沒有足夠的空光碟,沒法保證每個人都能拿到燒錄上資料的光碟,又來不及去買了,怎麼辦呢?組委會把這個難題交給了lhc,lhc分析了一下所有營員...

洛谷 P2835 燒錄光碟

其實這題水的一批.在jsoi2005夏令營快要結束的時候,很多營員提出來要把整個夏令營期間的資料燒錄成一張光碟給大家,以便大家回去後繼續學習。組委會覺得這個主意不錯!可是組委會一時沒有足夠的空光碟,沒法保證每個人都能拿到燒錄上資料的光碟,又來不及去買了,怎麼辦呢?組委會把這個難題交給了lhc,lhc...