【BIG # 2460】 桥 Bridges

topic

Title link: https://loj.ac/problem/2460

In an undirected graph, find an Euler loop with the smallest maximum edge weight. If not, output it NIE.

Ideas

The idea of ​​this question is quite good, the code size is not small, I feel it is a good question (?).

Because if the maximum value is \ (a \) , there is no way to form an Euler circuit. Obviously, when the maximum value is less than \ (a \) , you cannot form an Euler circuit. So decisive dichotomy.

Then this undirected graph was split into a graph with both bidirectional edges and unidirectional edges. Then we need to change the direction of the bidirectional edge to make this graph a directed graph with Euler loops.

The judgment of the Euler circuit is that there is no unequal outgoing and incoming degrees of any point.

We assume any direction for each bidirectional edge. Then find the difference of \ (deg \) representing the in-degree and out-degree of each point . Obviously we need to change the direction of the bidirectional edges so that all points have \ (deg = 0 \) .

Consider network flow. If a \ (deg [x] \ geq 0 \) , then the edge \ ((S, x, \ frac {deg [x]} {2}) \) , if \ (deg [x] <0 \) , Then connect the edges \ ((x, T, \ frac {-deg [x]} {2}) \) .

If we assume \ (a \ to b \) for a bidirectional edge , then if we want to reverse this edge, it will result in \ (deg [a] -2, deg [b] +2 \) . So even edges \ ((a, b, 1) \) .

Obviously, the sufficient condition of the above model is

  • There is no edge that satisfies both weights greater than \ (mid \) .
  • \ (Deg \) without edges is odd.

So if one of the above two conditions is not satisfied, just return directly.

When \ (∀i \) satisfies \ (deg [i] = 0 \) , obviously the flow is \ (\ frac {\ sum ^ {n} _ {i = 1} \ operatorname {abs} deg [i]} {2} \) . Just judge whether it is full flow.

When we find the answer, we take out the network graph corresponding to the answer. For the two-way edge, if there is traffic flowing through, it is equivalent to this edge to be reversed.

Then we get a directed graph and this graph must have Euler loops, and the weight of each edge does not exceed the answer. Then directly find the Euler circuit with dfs.

Time complexity \ (O (n ^ 2m \ log a_i) \) .

Code

I feel that this question code has been ugly for a long time recently. . .

#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=2010,M=100010,Inf=1e9+114514;
int n,m,S,T,tot,top,L,R,Mid,maxflow,deg[N],last[N],head[N],st[N],out[N];
bool vis[M],WYCtql;
vector<int> r[N];

struct edge1
{
	int from,to,a,b;
}e[M];

void add(int from,int to,int a,int b)
{
	e[++tot].to=to;
	e[tot].from=from;
	e[tot].a=a;
	e[tot].b=b;
}

struct edge2
{
	int next,to,flow;
}ans[M];

struct edge3
{
	int next,to;
}ee[M];

void add2(int from,int to)
{
	out[from]++;
	ee[++tot].to=to;
	ee[tot].next=head[from];
	head[from]=tot;
}

struct Dinic
{
	int tot,head[N],cur[N],dep[N];
	edge2 e[M];
	
	void clr()
	{
		memset(head,-1,sizeof(head));
		tot=1;
	}
	
	void add(int from,int to,int flow)
	{
		e[++tot].to=to;
		e[tot].flow=flow;
		e[tot].next=head[from];
		head[from]=tot;
		swap(from,to);
		e[++tot].to=to;
		e[tot].flow=0;
		e[tot].next=head[from];
		head[from]=tot;
	}
	
	bool bfs()
	{
		memcpy(cur,head,sizeof(cur));
		memset(dep,0x3f3f3f3f,sizeof(dep));
		queue<int> q; q.push(S);
		dep[S]=0;
		while (q.size())
		{
			int u=q.front();
			q.pop();
			for (int i=head[u];~i;i=e[i].next)
			{
				int v=e[i].to;
				if (e[i].flow && dep[v]>dep[u]+1)
				{
					dep[v]=dep[u]+1;
					q.push(v);
				}
			}
		}
		return dep[T]<Inf;
	}
	
	int dfs(int x,int flow)
	{
		int ret=0,used=0;
		if (x==T)
		{
			maxflow+=flow;
			return flow;
		}
		for (int i=cur[x];~i;i=e[i].next)
		{
			int v=e[i].to;
			cur[x]=i;
			if (e[i].flow && dep[x]==dep[v]-1)
			{
				ret=dfs(v,min(flow-used,e[i].flow));
				if (ret)
				{
					used+=ret;
					e[i].flow-=ret; e[i^1].flow+=ret;
					if (used==flow) break;
				}
			}
		}
		return used;
	}
	
	void dinic()
	{
		maxflow=0;
		while (bfs()) dfs(S,Inf);
	}
}dinic;

bool check(int mid)
{
	memset(deg,0,sizeof(deg));
	for (int i=1;i<=m;i++)
	{
		if (min(e[i].a,e[i].b)>mid) return 0;
		if (e[i].a<=mid)
			deg[e[i].from]++,deg[e[i].to]--;
		else
			deg[e[i].to]++,deg[e[i].from]--;
	}
	dinic.clr();
	for (int i=1;i<=m;i++)
		if (e[i].a<=mid && e[i].b<=mid)
			dinic.add(e[i].from,e[i].to,1);
	int sum=0;
	for (int i=1;i<=n;i++)
	{
		if (abs(deg[i])&1) return 0;
		deg[i]/=2; sum+=abs(deg[i]);
		if (deg[i]>=0) dinic.add(S,i,deg[i]);
			else dinic.add(i,T,-deg[i]);
	}
	dinic.dinic();
	return maxflow==sum/2;
}

void print(int x)
{
    for (int i=head[x];~i;i=ee[i].next)
	{
        int k=i;
        if (!vis[k]) {
            vis[k]=1;
            print(ee[k].to);
            st[++top]=k;
        }
    }
}

int main()
{
	memset(head,-1,sizeof(head));
	scanf("%d%d",&n,&m);
	srand(n+m+23333);
	L=Inf; S=N-1; T=N-2;
	for (int i=1,x,y,a,b;i<=m;i++)
	{
		scanf("%d%d%d%d",&x,&y,&a,&b);
		add(x,y,a,b);
		L=min(L,min(a,b)); R=max(R,max(a,b));
	}
	bool flag=0;
	while (L<=R)
	{
		Mid=(L+R)>>1;
		if (check(Mid))
		{
			R=Mid-1; flag=1;
			memcpy(ans,dinic.e,sizeof(ans));
		}
		else L=Mid+1;
	}
	if (flag) printf("%d\n",R+1);
		else return !printf("NIE");
	tot=0;
	for (int i=1,j=0;i<=m;i++)
		if (e[i].a<=R+1 && e[i].b<=R+1)
		{
			j++;
			if (!ans[j*2].flow)
				add2(e[i].to,e[i].from);
			else
				add2(e[i].from,e[i].to);
		}
		else if (e[i].a<=R+1)
			add2(e[i].from,e[i].to);
		else
			add2(e[i].to,e[i].from);
	print(1);
	for (int i=m;i>=1;i--)
		printf("%d ",st[i]);
	return 0;
}

Guess you like

Origin www.cnblogs.com/stoorz/p/12758701.html