CODEVS P2833 奇怪的夢境
阿新 • • 發佈:2018-11-08
2833 奇怪的夢境
時間限制: 1 s 空間限制: 128000 KB 題目等級 : 黃金 Gold 題目描述 Description
Aiden陷入了一個奇怪的夢境:他被困在一個小房子中,牆上有很多按鈕,還有一個螢幕,上面顯示了一些資訊。螢幕上說,要將所有按鈕都按下才能出去,而又給出了一些資訊,說明了某個按鈕只能在另一個按鈕按下之後才能按下,而沒有被提及的按鈕則可以在任何時候按下。可是Aiden發現螢幕上所給資訊似乎有矛盾,請你來幫忙判斷。
第一行,兩個數N,M,表示有編號為1...N這N個按鈕,螢幕上有M條資訊。
接下來的M行,每行兩個數ai,bi,表示bi按鈕要在ai之後按下。所給資訊可能有重複,保證ai≠bi。
輸出描述 Output Description若按鈕能全部按下,則輸出“o(∩_∩)o”。
若不能,第一行輸出“T_T”,第二行輸出因資訊有矛盾而無法確認按下順序的按鈕的個數。輸出不包括引號。
3 3
1 2
2 3
3 2
樣例輸出 Sample OutputT_T
2
資料範圍及提示 Data Size & Hint對於30%的資料,保證0<N≤100。
對於50%的資料,保證0<N≤2000。
對於70%的資料,保證0<N≤5000。
對於100%的資料,保證0<N≤10000,0<M≤2.5N。
隨便找了一道純拓撲排序的題練了一下,感覺就是個模板題,非常水,畢竟難度等級只有這麼低。
看懂題目的意思發現其實就是ai到bi建一條有向邊,建完邊之後跑一邊拓撲排序,最後判斷是否所有點都能刪了。
如果有環,就表明不能打成目標,直接輸出總點數-已刪點數就行了。
至於拓撲排序的方法到處都有,我就不作解釋了。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=100001;
struct edge
{
int node,next,w;
}h[MAXN];//這個資料要用鄰接表來存
int Head[MAXN],Dg[MAXN],stack[MAXN];//這裡我用的棧,感覺比較順手,其實都無所謂就是順序不一樣。
int n,m,tot,top=0,sum=0;
void add(int u,int v)//鄰接表加邊
{
h[++tot].next=Head[u];
h[tot].node=v;
Head[u]=tot;
}
void push(int x)
{
stack[++top]=x;
}
int pop()
{
return stack[top--];
}//棧的兩個操作
void TPsort()//拓撲排序
{
for(int i=1;i<=n;i++)
if(!Dg[i])
push(i);
int v;
while(top)
{
int x=pop();
sum++;
for(int i=Head[x];i;i=h[i].next)
{
v=h[i].node;
if(Dg[v])
Dg[v]--;
if(!Dg[v])
push(v);
}
}
if(sum==n)
cout<<"o(∩_∩)o";
else
cout<<"T_T"<<endl<<n-sum;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
add(x,y);
Dg[y]++;
}
TPsort();
return 0;
}