【CF387D】George and Interesting Graph(二分图最大匹配)

题意:给定一张n点m边没有重边的有向图,定义一个有趣图为:存在一个中心点满足以下性质:

1、除了这个中心点之外其他的点都要满足存在两个出度和两个入度。

2、中心 u 需要对任意顶点 v(包括自己)有一条(u,v)的边和(v,u)的边,即他们都要互通。

现在可以删除和添加边,使得给出的原图满足以上情况。询问删除和添加的最小操作次数。

n<=500,m<=1000

思路:枚举中心u,将边分为不相同的三部分:

1.u的自环,记为cir=(0..1)

2.u的出边或入边,记为out与in

3.与u无关的边

存在以下性质:原图删去中心以及1,2类边后每个点的出度与入度都为1

相当于一个点裂成了一个出点与入点,对这些点与边跑二分图最大匹配

考虑答案也有三部分组成:

1.原图中无用的边,即m-in-out-cir-maxmatch

2.需要添加的与中心无关的边,即n-1-maxmatch

3.需要添加的与中心相关的边,即2*(n-1)-in-out+1-cir

三部分加起来即为所求

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<string>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<map>
 8 #include<set>
 9 #include<queue>
10 #include<vector>
11 using namespace std;
12 typedef long long ll;
13 typedef unsigned int uint;
14 typedef unsigned long long ull;
15 typedef pair<int,int> PII;
16 typedef vector<int> VI;
17 #define fi first
18 #define se second
19 #define MP make_pair
20 #define N   1100
21 #define M   1100
22 #define eps 1e-8
23 #define pi  acos(-1)
24 #define oo  1e9
25 
26 int head[N],vet[N],nxt[N],match[N],flag[N],x[N],y[N],n,m,tot;
27 
28 int add(int a,int b)
29 {
30     nxt[++tot]=head[a];
31     vet[tot]=b;
32     head[a]=tot;
33 }
34 
35 int dfs(int u)
36 {
37     flag[u]=1;
38     int e=head[u];
39     while(e)
40     {
41         int v=vet[e];
42         if(!match[v]||!flag[match[v]]&&dfs(match[v]))
43         {
44             match[v]=u;
45             return 1;
46         }
47         e=nxt[e];
48     }
49     return 0;
50 }
51 
52 int calc(int mid)
53 {
54     int in=0;
55     int out=0;
56     int cir=0;
57     memset(head,0,sizeof(head));
58     tot=0;
59     for(int i=1;i<=m;i++)
60     {
61         if(x[i]==mid&&y[i]==mid) 
62         {
63             cir=1;
64             continue;
65         }
66         if(y[i]==mid){in++; continue;}
67         if(x[i]==mid){out++; continue;}
68         add(x[i],y[i]);
69     }
70     
71     memset(match,0,sizeof(match));
72     int maxmatch=0;
73     for(int i=1;i<=n;i++)
74     {
75         memset(flag,0,sizeof(flag));
76         if(dfs(i)) maxmatch++;
77     }
78     int del=m-in-out-cir-maxmatch; //无用,删 
79     int plus=n-1-maxmatch;    //无关中心,加 
80     int t=2*(n-1)-in-out+1-cir; //中心相关 
81     return del+plus+t; 
82 }
83 
84 int main()
85 {
86     //freopen("cf387d.in","r",stdin);
87     //freopen("cf387d.out","w",stdout);
88     scanf("%d%d",&n,&m);
89     for(int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]);
90     int ans=oo;
91     for(int i=1;i<=n;i++) ans=min(ans,calc(i));
92     printf("%d\n",ans);
93     return 0;
94 }
95     
96     

猜你喜欢

转载自www.cnblogs.com/myx12345/p/9838995.html
今日推荐