4316: 小C的独立集
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 472 Solved: 263
[ Submit][ Status][ Discuss]
Description
图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨。
这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多。
小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很有特点的图: 图中任何一条边属于且仅属于一个简单环,图中没有重边和自环。小C说这样就会比较水了。
小D觉得这个题目很有趣,就交给你了,相信你一定可以解出来的。
Input
第一行,两个数n, m,表示图的点数和边数。
第二~m+1行,每行两个数x,y,表示x与y之间有一条无向边。
Output
输出这个图的最大独立集。
Sample Input
5 6
1 2
2 3
3 1
3 4
4 5
3 5
1 2
2 3
3 1
3 4
4 5
3 5
Sample Output
2
HINT
100% n <=50000, m<=60000
Source
#include<cstdio> #include<ctime> #include<cstdlib> #include<vector> #include<algorithm> #include<queue> #include<cstring> using namespace std; typedef long long LL; const int INF = 2147483647; const int maxn = 50010 * 2; vector<int> e[maxn],ei[maxn]; int n,m,tot,ans,fa[maxn]; int g[maxn][2],f[maxn][2]; int stk[maxn],top,low[maxn],dfn[maxn],tme,rec[maxn]; int tmp[maxn],vis[maxn]; inline int getint() { int ret = 0; char c = getchar(); while (c < '0' || '9' < c) c = getchar(); while ('0' <= c && c <= '9') ret = ret * 10 + c - '0',c = getchar(); return ret; } inline void tarjan(int u,int fa) { stk[++top] = u; dfn[u] = low[u] = ++tme; for (int i = 0; i < ei[u].size(); i++) { int v = ei[u][i]; if (v == fa) continue; if (!dfn[v]) { tarjan(v,u); low[u] = min(low[u],low[v]); if (dfn[u] <= low[v]) { int all = 0; ++tot; while (low[stk[top]] >= dfn[u] && u != stk[top]) { int p = stk[top--]; e[p].push_back(tot); e[tot].push_back(p); all++; } e[u].push_back(tot); e[tot].push_back(u); all++; /* if (all > 2) { printf("u : %d",u); for (int i = 1; i <= all; i++) tmp[i] = e[tot][i - 1]; putchar('\n'); for (int i = 1; i <= all; i++) printf("%d ",tmp[i]); printf("\ndfn\n"); for (int i = 1; i <= all; i++) printf("%d ",dfn[tmp[i]]); printf("\nlow\n"); for (int i = 1; i <= all; i++) printf("%d ",low[tmp[i]]); putchar('\n'); for (int i = 1; i <= all; i++) { printf("%d : ",tmp[i]); for (int j = 0; j < ei[tmp[i]].size(); j++) printf("%d ",ei[tmp[i]][j]); putchar('\n'); } putchar('\n'); } */ rec[tot] = 1; } } else low[u] = min(low[u],dfn[v]); } } inline void trans(int now) { for (int i = 2; i <= now; i++) { g[i][0] = max(g[i - 1][1] , g[i - 1][0]) + (now == i ? 0 : f[tmp[i]][0]); g[i][1] = g[i - 1][0] + (now == i ? 0 : f[tmp[i]][1]); } } inline void clear(int now) { for (int i = 1; i <= now; i++) g[i][0] = g[i][1] = 0; } inline void dp(int u) { int pos,now = 0; for (int i = 0; i < e[u].size(); i++) { int v = e[u][i]; if (fa[u] == v) { pos = i; break; } } for (int i = pos + 1; i < e[u].size(); i++) tmp[++now] = e[u][i]; for (int i = 0; i <= pos; i++) tmp[++now] = e[u][i]; clear(now); g[1][1] = f[tmp[1]][1]; g[1][0] = f[tmp[1]][0]; trans(now); f[u][0] = g[now][0]; clear(now); g[1][1] = -INF; g[1][0] = f[tmp[1]][0]; trans(now); f[u][1] = g[now][1]; } inline void Dp(int u) { if (!rec[u]) f[u][1]++; vis[u] = 1; for (int i = 0; i < e[u].size(); i++) { int v = e[u][i]; if (v == fa[u]) continue; fa[v] = u; Dp(v); if (!rec[u]) f[u][0] += f[v][0] , f[u][1] += f[v][1]; } if (rec[u]) dp(u); } int main() { #ifdef AMC freopen("AMC1.txt","r",stdin); freopen("AMC2.txt","w",stdout); #endif n = getint(); m = getint(); for (int i = 1; i <= m; i++) { int u = getint(),v = getint(); ei[u].push_back(v); ei[v].push_back(u); } tot = n; for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i,0); for (int i = 1; i <= tot; i++) if (!vis[i]) { Dp(i); ans += max(f[i][0],f[i][1]); } printf("%d",ans); return 0; }