題意就是設置最少的哨兵,可以看到全部的路。ios
二分圖也能解決,即二分圖最小點覆蓋 用vector超內存了,ide
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 #define MAXN 1600 6 #define MAXE 300000 7 struct Edge 8 { 9 int v; // 10 int next; 11 }edge[MAXE]; 12 int head[MAXN]; // 每一個點臨接的邊 13 int cnt ; // 邊的條數 14 int n ; // 點的個數 15 int path[MAXN]; 16 bool used[MAXN]; 17 void add(int u,int v) 18 { 19 edge[cnt].v = v; 20 edge[cnt].next = head[u]; 21 head[u] = cnt++; 22 23 edge[cnt].v = u; 24 edge[cnt].next = head[v]; 25 head[v] = cnt++; 26 } 27 bool dfs(int u) 28 { 29 for(int i = head[u]; i != -1; i = edge[i].next) 30 { 31 int v = edge[i].v; 32 if(!used[v]) 33 { 34 used[v] = true; 35 if(path[v] == -1 || dfs(path[v])) 36 { 37 path[v] = u; 38 return true; 39 } 40 } 41 } 42 return false; 43 } 44 int match() 45 { 46 int res = 0; 47 memset(path,-1,sizeof(path)); 48 for(int u = 0; u < n; u++) 49 { 50 memset(used,0,sizeof(used)); 51 if(dfs(u)) 52 res++; 53 } 54 return res; 55 } 56 int main() 57 { 58 //freopen("Input.txt","r",stdin); 59 while(scanf("%d",&n) != EOF) 60 { 61 memset(edge,0,sizeof(edge)); 62 memset(head,-1,sizeof(head)); 63 cnt = 0; 64 for(int i = 0; i < n; i++) 65 { 66 int a,b,c; 67 scanf("%d:(%d)",&a,&b); 68 while(b--) 69 { 70 scanf("%d",&c); 71 add(a,c); 72 } 73 } 74 cout<<match()/2<<endl; 75 } 76 return 0; 77 }
用樹形dp求解即,每一個點都有設哨兵和不設哨兵。dp1爲設置哨兵,dp2爲不設置哨兵。spa
則 dp1【s】 + =min(dp1【x】,dp2【x】);//s爲父節點,x爲子節點。 code
dp2【s】 + = sum{ dp1【x】}; 父節點不設置哨兵,則其子節點都要設置哨兵。blog
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<vector> 5 using namespace std; 6 vector<int>V[1500]; 7 int vis[1500]; 8 int dp1[1500],dp2[1500];//設和不設 9 void init() 10 { 11 for(int i=0;i<1500;i++) 12 { 13 V[i].clear(); 14 dp1[i]=1; 15 dp2[i]=0; 16 } 17 memset(vis,0,sizeof(vis)); 18 } 19 void dfs(int s) 20 { 21 vis[s]=1; 22 for(int i=0;i<(int)V[s].size();i++) 23 { 24 int x=V[s][i]; 25 if(!vis[x]) 26 { 27 dfs(x); 28 dp2[s]+=dp1[x]; 29 dp1[s]+=min(dp1[x],dp2[x]); 30 } 31 } 32 } 33 int main() 34 { 35 //freopen("Input.txt","r",stdin); 36 int n,i,j,k,x; 37 while(~scanf("%d",&n)) 38 { 39 init(); 40 for(i=1;i<=n;i++) 41 { 42 scanf("%d:(%d)",&j,&k); 43 while(k--) 44 { 45 scanf("%d",&x); 46 V[j].push_back(x); 47 V[x].push_back(j); 48 } 49 } 50 dfs(0); 51 printf("%d\n",min(dp1[0],dp2[0])); 52 } 53 return 0; 54 }