bzoj 1574: [Usaco2009 Jan]地震损坏Damage
Description
农夫John的农场遭受了一场地震.有一些牛棚遭到了损坏,但幸运地,所有牛棚间的路经都还能使用. FJ的农场有P(1 <= P <= 30,000)个牛棚,编号1..P. C(1 <= C <= 100,000)条双向路经联接这些牛棚,编号为1..C. 路经i连接牛棚a_i和b_i (1 <= a_i<= P;1 <= b_i <= P).路经可能连接a_i到它自己,两个牛棚之间可能有多条路经.农庄在编号为1的牛棚. N (1 <= N <= P)头在不同牛棚的牛通过手机短信report_j(2 <= report_j <= P)告诉FJ它们的牛棚(report_j)没有损坏,但是它们无法通过路经和没有损坏的牛棚回到到农场. 当FJ接到所有短信之后,找出最小的不可能回到农庄的牛棚数目.这个数目包括损坏的牛棚. 注意:前50次提交将提供在一些测试数据上的运行结果.
Input
* 第1行: 三个空格分开的数: P, C, 和 N
* 第2..C+1行: 每行两个空格分开的数: a_i 和 b_i * 第C+2..C+N+1行: 每行一个数: report_j
Output
* 第1行: 一个数,最少不能回到农庄的牛的数目(包括损坏的牛棚).
Sample Input
4 3 1
1 2
2 3
3 4
3
1 2
2 3
3 4
3
Sample Output
3
HINT
牛棚2遭到损坏,导致牛棚2, 3, 4里面的牛无法回到农庄.
思路: 本题为贪心+灌水,按照贪心原则,如果一个点不能到1,那么他的相邻的所有点都是坏的。
然后我们从1开始去灌水找到还有多少点能到。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define rep(i,a,b) for(R i=a;i<=b;i++) 5 #define Rep(i,a,b) for(R i=a;i>=b;i--) 6 #define rp(i,x) for(R i=H[x];i;i=e[i].nt) 7 #define ms(i,a) memset(a,i,sizeof(a)) 8 #define gc() getchar() 9 template<class T>void read(T &x){ 10 x=0; char c=0; 11 while (!isdigit(c)) c=gc(); 12 while (isdigit(c)) x=x*10+(c^48),c=gc(); 13 } 14 int const N=30000+3; 15 int const M=100000+3; 16 struct edge{ 17 int to,nt; 18 }e[M<<1]; 19 int vis[N],n,cnt,H[N],p,c,ans; 20 void add(int a,int b){ 21 e[++cnt]=(edge){b,H[a]}; H[a]=cnt; 22 } 23 void dfs(int x){ 24 ans--; 25 vis[x]=1; 26 rp(i,x) { 27 int v=e[i].to; 28 if(!vis[v]) dfs(v); 29 } 30 } 31 int main(){ 32 read(p); read(c); read(n); 33 while (c--){ 34 int x,y; 35 read(x); read(y); 36 add(x,y); add(y,x); 37 } 38 while (n--){ 39 int x; read(x); 40 rp(i,x) vis[e[i].to]=1; 41 } 42 ans=p; 43 dfs(1); 44 cout<<ans<<endl; 45 return 0; 46 } 47