Time Limit: 3000MS | Memory Limit: 10000K | |
Total Submissions: 1447 | Accepted: 693 |
Description
Input
Output
Sample Input
3 101 0 3 3 1 2 1 3 1 1 8 12 1 1 1 2 1 3 1 4 2 5 3 5 4 5 5 5 6 6 7 6 8 7 8 8
Sample Output
50 0 3
Source
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXN 210 struct LEdge{ int ed, next; }edge[MAXN * MAXN]; int head[2 * MAXN], nEdge; void init(){ nEdge = 0; memset(head, 0xff, sizeof(head)); } void addEdge(int i, int j){ edge[nEdge].ed = j; edge[nEdge].next = head[i]; head[i] = nEdge++; } int f[MAXN][MAXN]; int vis[MAXN][2]; int m, r; int np, nq; void dfs(int cur, int flag){ int i; if (!flag) np++; else nq++; vis[cur][flag] = 1; for (i = head[2 * cur + flag]; i != -1; i = edge[i].next){ if (vis[edge[i].ed / 2][1 - flag]) continue; dfs(edge[i].ed / 2, 1 - flag); } } void dp(int np, int nq){ int j, k; for (j = m / 2; j >= 0; j--){ for (k = m / 2; k >= 0; k--){ if (j - np >= 0 && k - nq >= 0){ f[j][k] |= f[j - np][k - nq]; } } } } int main(){ int i, j, k, T; scanf("%d", &T); while(T--){ init(); scanf("%d%d", &m, &r); for (k = 0; k < r; k++){ scanf("%d%d", &i, &j); addEdge(2 * i, 2 * j + 1); addEdge(2 * j + 1, 2 * i); } memset(vis, 0, sizeof(vis)); memset(f, 0, sizeof(f)); f[0][0] = 1; for (i = 1; i <= m; i++){ if (!vis[i][0]){ np = nq = 0; dfs(i, 0); // printf("i = %d, flag = %d, np = %d, nq = %d\n", i, 0, np, nq); dp(np, nq); } if (!vis[i][1]){ np = nq = 0; dfs(i, 1); // printf("i = %d, flag = %d, np = %d, nq = %d\n", i, 1, np, nq); dp(np, nq); } if (f[m / 2][m / 2]) break; } for (i = m / 2; i >= 0; i--) if (f[i][i]) break; printf("%d\n", i); } return 0; } /* 开始看样例的时候注意到了,但是写的时候却忽略了,尤其在邻接表建边的时候,读进来直接就往里加边... 因为这个WA了一次,感觉没有坑,过了样例就行 简述下算法 预处理,将人分成互相有影响的几个集合,集合内的人要走就必须全部走。把集合看做一个属性为(p,q)的物品(表示prison1中有p人,prison2中有q人)放到背包(m/2,m/2)中 当然,无影响的人就是(1,0)或(0,1) 然后,普通的可行性背包 开始想到了背包,但是纠结于怎么表达一个人影响其他许多人,总觉得用图表示什么的... 没想到预处理下就好了... */