• [CF343E] Pumping Stations


    前言

    这题还是有点意思的。

    题目

    洛谷

    CF

    讲解

    首先我们要先把最小割树建出来,如果你此时和我一样打算先把两两之间的最小割求出来再考虑构造可能就会走不少弯路,甚至做不出来。

    我们就考虑这棵最小割树,由于我们构造的是一个排列,两个点之间的最小割是最小割树的路径权值(最小值),且我们要构造使得排列权值和最大,其实就是在这棵树上乱走,感性的来讲,我们要尽可能少经过权值小的边

    这时我们就可以发现由于构造的是排列,那么每条边都必定至少被经过一次,否则不可能走到所有的点。

    于是我们试图使得最小的边只经过一次,然后递归两边的子树做子问题,这个解法本身就可以用分治实现,但是我比较懒,而且比较呆,想不出更好的做法,于是去看题解。

    直接贪心bfs就可以了!我觉得窃取别人的证明不大好,所以我这里贴一个meyi大佬的博客,可以去看祂的证明。

    复杂度瓶颈依然是建树。

    代码

    //12252024832524
    #include <bits/stdc++.h>
    #define TT template<typename T>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 205;
    const int MAXM = 1005;
    const int INF = 0x3f3f3f3f;
    int n,m;
    
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    int head[MAXN],tot = 1,cur[MAXN];
    struct edge{
    	int v,w,nxt;
    }e[MAXM<<1];
    void Add_Edge(int u,int v,int w){
    	e[++tot] = edge{v,w,head[u]};
    	head[u] = tot;
    } 
    void Add_Double_Edge(int u,int v,int w){
    	Add_Edge(u,v,w);
    	Add_Edge(v,u,w);
    }
    
    int dis[MAXN];
    bool bfs(int S,int T){
    	for(int i = 1;i <= n;++ i) dis[i] = n; 
    	queue<int> q; q.push(S); dis[S] = 0;
    	while(!q.empty()) {
    		int x = q.front(); q.pop();
    		for(int i = head[x],v; i ;i = e[i].nxt)
    			if(e[i].w && dis[x] + 1 < dis[v = e[i].v])
    				dis[v] = dis[x] + 1,q.push(v);
    	}
    	return dis[T] < n;
    }
    int dfs(int x,int flow,int T){
    	if(x == T) return flow;
    	int ret = 0;
    	for(int &i = cur[x],v,val; i ;i = e[i].nxt)
    		if(e[i].w && dis[x] + 1 == dis[v = e[i].v]){
    			val = dfs(v,Min(flow-ret,e[i].w),T);
    			e[i].w -= val; e[i^1].w += val;
    			if((ret += val) == flow) break;
    		}
    	return ret;
    }
    int dinic(int S,int T){
    	int ret = 0;
    	for(int i = 2;i <= tot;i += 2) e[i].w = e[i^1].w = (e[i].w+e[i^1].w) >> 1;
    	while(bfs(S,T)){
    		for(int i = 1;i <= n;++ i) cur[i] = head[i];
    		ret += dfs(S,INF,T);
    	}
    	return ret;
    }
    
    int ID[MAXN],S;
    bool vis[MAXN];
    vector<pair<int,int> > G[MAXN];
    void findp(int x)
    {
    	vis[x] = 1;
    	for(int i = head[x],v; i ;i = e[i].nxt)
    		if(e[i].w && !vis[v = e[i].v])
    			findp(v);
    }
    void solve(int l,int r){
    	if(l >= r) return;
    	int mf = dinic(ID[l],ID[l+1]); S += mf;
    	G[ID[l]].emplace_back(make_pair(mf,ID[l+1]));
    	G[ID[l+1]].emplace_back(make_pair(mf,ID[l]));
    	for(int i = 1;i <= n;++ i) vis[i] = 0;
    	findp(ID[l]);
    	sort(ID+l,ID+r+1,[](int x,int y){return vis[x] < vis[y];});
    	for(int i = l;i <= r;++ i)
    		if(vis[ID[i]]) {solve(l,i-1);solve(i,r);break;}
    }
    int rt,cut[MAXN][MAXN];
    void dfs2(int x,int fa,int d){
    	cut[rt][x] = d;
    	for(auto &A : G[x])
    		if(A.second != fa)
    			dfs2(A.second,x,Min(d,A.first));
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); m = Read();
    	for(int i = 1,u,v;i <= m;++ i) u = Read(),v = Read(),Add_Double_Edge(u,v,Read());
    	for(int i = 1;i <= n;++ i) ID[i] = i;
    	solve(1,n);
    	for(int i = 1;i <= n;++ i) dfs2(rt = i,0,INF);
    	Put(S,'\n');
    	priority_queue<pair<int,int> > q;
    	q.push(make_pair(0,1));
    	for(int i = 1;i <= n;++ i) vis[i] = 0; vis[1] = 1;
    	while(!q.empty()){
    		pair<int,int> t = q.top(); q.pop(); Put(t.second,' ');
    		for(auto &A : G[t.second])
    			if(!vis[A.second])	
    				q.push(A),vis[A.second] = 1;
    	}
    	return 0;
    }
    
  • 相关阅读:
    c#基于事件模型的UDP通讯框架(适用于网络包编解码)
    菜鸟的mongoDB学习---(五)MongoDB的limit、skip、sort方法
    Session管理之ThreadLocal
    java中a++和++a在较复杂的运算中分析
    Spring2.5学习4.2_Proxy实现动态代理(目标类实现随意接口)
    申请美国签证超具体流程
    Class 与 new的配合使用
    关注PHPthinking官网微信公众号——红包来袭
    oracle-sql优化器
    POJ 2184 Cow Exhibition
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15921161.html
Copyright © 2020-2023  润新知