How Many to Be Happy? Gym - 101667E

How Many to Be Happy?

 Gym - 101667E 

题目大意:给出一个无向图,令使得一条边e成为这个图的最小生成树的一条树边需要删去的最少的边的数量为H(e),问H(e)地总和是多少

思路:

对于一幅图我们构造最小生成树地时候总是先选较小的边再选择较大的边,且一个点数确定的图(假设为m)其边数也是确定的m-1,想要e进入这幅图的最小生成树就要让所有边权小于e的边构成的图恰好不能形成一个树,且可以通过e来使其连接成一个最小生成树。因此就需要用所有边权小于e的边构成的图,使e的两个端点为源点和汇点,跑出一个最小割。再对所有的边都跑出这个最小割,求和即是答案。

#include<queue>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=205;//点数
const int inf=0x3f3f3f3f;
struct Edge{
	int from,to,cap,flow;//起点,终点,容量,流量
	Edge(){}
	Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){}
};
struct Dinic{
	int n,m,s,t;
	vector<Edge> edges;
	vector<int> G[maxn];//邻接表
	bool vis[maxn];//BFS使用
	int d[maxn];//从起点到i的距离
	int cur[maxn];//当前弧下标

	void init(int n)//n为点的数量
	 {
	 	this->n=n;
	 	for(int i=0;i<n;i++) G[i].clear();
	 	edges.clear();
	 }


	void AddEdge(int from,int to,int cap)//增加边
	{
		edges.push_back(Edge(from,to,cap,0));
		edges.push_back(Edge(to,from,0,0));
		m=edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}


	bool bfs()//用bfs来构筑层次图
	{
		memset(vis,0,sizeof(vis));
		queue<int> Q;
		Q.push(s);
		d[s]=0;
		vis[s]=1;
		while(!Q.empty())
		{
			int x=Q.front();Q.pop();
			for(int i=0;i<G[x].size();i++)
			{
				Edge& e=edges[G[x][i]];
				if(!vis[e.to]&&e.cap>e.flow)//只考虑参与网络的弧
				{
					vis[e.to]=1;
					d[e.to]=d[x]+1;
					Q.push(e.to);
				}
			}
		}
		return vis[t];
	}


	int dfs(int x,int a)//用dfs构筑增广路
	{
		if(x==t||a==0) return a;
		int flow=0,f;
		for(int& i=cur[x]; i<G[x].size() ;i++)
		{
			Edge& e=edges[G[x][i]];
			if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if(!a) break;
			}
		}
		return flow;
	}


	int Maxflow(int s,int t)//求最大流
	{
		this->s=s,this->t=t;
		int flow=0;
		while(bfs())//s,t不再联通此时,打过标记的点就是最小的S
		{
			memset(cur,0,sizeof(cur));
			flow+=dfs(s,inf);
		}
		return flow;
	}
};
struct Edges{
	int u,v,w;
	Edges(){}
	Edges(int u,int v,int w):u(u),v(v),w(w){}
};
vector<Edges> V;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    V.clear();
    for(int i=1;i<=m;i++)
    {
    	int u,v,w;
    	scanf("%d%d%d",&u,&v,&w);
		V.push_back(Edges(u,v,w));
	}
	int ans=0;
	for(int i=0;i<V.size();i++)
	{
		Dinic pro;
		pro.init(n);
		for(int j=0;j<V.size();j++)
		{
			if(i==j) continue;
			if(V[j].w<V[i].w)
			{
				pro.AddEdge(V[j].u,V[j].v,1);
				pro.AddEdge(V[j].v,V[j].u,1);
			}
		}
		ans+=pro.Maxflow(V[i].u,V[i].v);
	}
	cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/baiyifeifei/article/details/82779789