Codeforces 387D George and Interesting Graph【思维+二分匹配】

来源:互联网 发布:网络直播方案 编辑:程序博客网 时间:2024/05/17 14:16

D. George and Interesting Graph
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

George loves graphs. Most of all, he loves interesting graphs. We will assume that a directed graph is interesting, if it meets the following criteria:

  • The graph doesn't contain any multiple arcs;
  • There is vertex v (we'll call her the center), such that for any vertex of graph u, the graph contains arcs (u, v) and (v, u). Please note that the graph also contains loop (v, v).
  • The outdegree of all vertexes except for the center equals two and the indegree of all vertexes except for the center equals two. The outdegree of vertex u is the number of arcs that go out of u, the indegree of vertex u is the number of arcs that go in u. Please note that the graph can contain loops.

However, not everything's that simple. George got a directed graph of n vertices and m arcs as a present. The graph didn't have any multiple arcs. As George loves interesting graphs, he wants to slightly alter the presented graph and transform it into an interesting one. In one alteration he can either remove an arbitrary existing arc from the graph or add an arbitrary arc to the graph.

George wonders: what is the minimum number of changes that he needs to obtain an interesting graph from the graph he's got as a present? Help George and find the answer to the question.

Input

The first line contains two space-separated integers n and m (2 ≤ n ≤ 500, 1 ≤ m ≤ 1000) — the number of vertices and arcs in the presented graph.

Each of the next m lines contains two space-separated integers ai, bi (1 ≤ ai, bi ≤ n) — the descriptions of the graph's arcs. Pair (ai, bi)means that the graph contains an arc from vertex number ai to vertex number bi. It is guaranteed that the presented graph doesn't contain multiple arcs.

Assume that the grah vertices are numbered 1 through n.

Output

Print a single integer — the answer to George's question.

Examples
input
3 71 12 23 11 33 22 33 3
output
0
input
3 61 12 23 13 22 33 3
output
1
input
3 12 2
output
6
Note

For more information about directed graphs, please visit: http://en.wikipedia.org/wiki/Directed_graph

In the first sample the graph already is interesting, its center is vertex 3.



题目大意:


给出N个点,M条边的有向图,现在我们可以任意添加一条边,也可以任意删除一条边,使得最终,有n-1个点的出度==入度并且出度为2.另外一个点设定为Center,并且要求这个点和其他各个点,都有两条边(u,v)和(v,u),并且不约束出度入度最终是多少。



思路:


①我们O(n)枚举这样一个中心点,然后暴力去判定这个Center和其他各个点都要相连的边是否缺少,如果缺少了的,都需要补上。


②然后我们此时如果搞定了Center点的约束之后,我们考虑剩下n-1个点,我们知道,最终要使得这n-1个点的出入度都是2,然而这里已经用掉了一个出度连入center点,也用掉了一个入度,使得center连入,那么我们剩下的任务就是将这n-1个点的出入度都控制在1即可。


③那么对于剩下的边,我们建图跑出最大二分匹配数,那么对于一个匹配来讲,我们将其保留,对于一条匹配边(u,v)来讲,我们就解决了点u的出度和点v的入度,那么如果我们能够将这n个点都匹配上,那么其实就相当于解决了所有点的问题,也就是说,此时所有点的出度和入度我们都控制在了1。

那么对于当前情况,我们跑出最大二分匹配数之后(maxn),如果其不足n-1个,那么补上(n-1-maxn),别忘了,还要删除原来存在的多余的边。


④过程维护一下,注意细节即可,时间复杂度O(n^2*m);


Ac代码:

#include<stdio.h>#include<string.h>#include<iostream>using namespace std;int match[600];int vis[600];int a[600][600];int x[4545];int y[4545];int n,m;int find(int u){    for(int i=1;i<=n;i++)    {        if(a[u][i]==1&&vis[i]==0)        {            vis[i]=1;            if(match[i]==-1||find(match[i]))            {                match[i]=u;                return 1;            }        }    }    return 0;}int Slove(int u){    int ans=0,tot=0;    memset(a,0,sizeof(a));    for(int i=1;i<=m;i++)a[x[i]][y[i]]=1;    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            if(a[i][j]==1&&(i!=u)&&(j!=u))tot++;            if(a[i][j]==0&&(i==u||j==u))            {                ans++;            }            if(i==u||j==u)a[i][j]=0;        }    }    memset(match,-1,sizeof(match));    int output=0;    for(int i=1;i<=n;i++)    {        memset(vis,0,sizeof(vis));        if(i==u)continue;        if(find(i))output++;    }    ans+=n-1-output;    ans+=tot-output;    return ans;}int main(){    while(~scanf("%d%d",&n,&m))    {        for(int i=1;i<=m;i++)        {            scanf("%d%d",&x[i],&y[i]);        }        int ans=0x3f3f3f3f;        for(int i=1;i<=n;i++)        {            int tmp=Slove(i);            ans=min(ans,tmp);        }        printf("%d\n",ans);    }}








阅读全文
1 0