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


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     
View Code

 

 

posted @ 2019-03-22 16:37  zjxxcn  阅读(149)  评论(0编辑  收藏  举报