题意:
给一个无向的双联通图...问最多留下多少条边使得每条边都没有共有顶点..
题解:
对边的两个端点v,u做两条边(u,v),(v,u)然后找最大匹配数,,,
有这么个问题..左右侧所代表的点是相同的..比如从左边1出发选择了右边的3..后面匹配时右边的1也不能选了...解决的方法是构造双向边(传统的是单向)..然后也是跑最大匹配...最后结果除以2
Program:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<string.h>
#include<queue>
#define ll long long
#define esp 1e-5
#define MAXN 5006
#define MAXM 100005
#define oo 100000007
using namespace std;
struct node
{
int y,next;
}line[MAXM];
int Lnum,_next[MAXN],match[MAXN];
bool used[MAXN];
void addline(int x,int y)
{
line[++Lnum].next=_next[x],_next[x]=Lnum,line[Lnum].y=y;
}
bool dfs(int x)
{
for (int k=_next[x];k;k=line[k].next)
{
int y=line[k].y;
if (used[y]) continue;
used[y]=true;
if (!match[y] || dfs(match[y]))
{
match[y]=x;
return true;
}
}
return false;
}
int getmax(int n)
{
int sum=0;
memset(match,0,sizeof(match));
for (int i=1;i<=n;i++)
{
memset(used,false,sizeof(used));
sum+=dfs(i);
}
return sum;
}
int main()
{
int cases,i,n,m;
scanf("%d",&cases);
while (cases--)
{
scanf("%d",&n);
m=3*n/2;
Lnum=0,memset(_next,0,sizeof(_next));
for (i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addline(x,y),addline(y,x);
}
printf("%d\n",getmax(n)/2);
}
return 0;
}
后来队友指出..这题不用做二分图匹配..直接n/2就是答案..有性质..(⊙o⊙)….
Program:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<string.h>
#include<queue>
#define ll long long
#define esp 1e-5
#define MAXN 5006
#define MAXM 100005
#define oo 100000007
using namespace std;
int main()
{
int cases,i,n,m,x,y;
scanf("%d",&cases);
while (cases--)
{
scanf("%d",&n);
m=3*n/2;
for (i=1;i<=m;i++) scanf("%d%d",&x,&y);
printf("%d\n",n/2);
}
return 0;
}