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;
}