UVA 11478V Halum 二分答案+差分约束系统

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

详细翻译版请见白皮书334页

11478 Halum
You are given a directed graph G(V, E) with a set of vertices and edges. Each edge (i, j) that connects
some vertex i to vertex j has an integer cost associated with that edge.
Define the operation Halum(v, d) to operate on a vertex v using an integer d as follows: subtract d
from the cost of all edges that enter v and add d to the cost of every edge that leaves v.
As an example of that operation, consider graph G that has three vertices named (1, 2, 3) and two
edges. Edge (1, 2) has cost -1, and edge (2,3) has cost 1. The operation Halum(2, −3) operates on
edges entering and leaving vertex 2. Thus, edge (1, 2) gets cost -1-(-3)=2 and the edge (2, 3) gets cost
1 + (-3) = -2.
Your goal is to apply the Halum function to a graph, potentially repeatedly, until every edge in the
graph has at least a certain cost that is greater than zero. You have to maximize this cost.
Input
Two space-separated integers per case: V (V ≤ 500) and E (E ≤ 2700). E lines follow. Each line
represents a directed edge using three space-separated integers (u, v, d). Absolute value of cost can be
at most 10000.
Output
If the problem is solvable, then print the maximum possible value. If there is no such solution print ‘No
Solution’. If the value can be arbitrary large print ‘Infinite’

Sample Input
2 1
1 2 10
2 1
1 2 -10
3 3
1 2 4
2 3 2
3 1 5
4 5
2 3 4
4 2 5
3 4 2
3 1 0
1 2 -1

Sample Output
Infinite
Infinite
3
1

分析:

对于一个点的多次操作相对独立,可以合成一个操作,记为s[x];

题目要求的是最小值的最大值,容易想到二分答案(赤裸裸的暗示啊)。

二分答案最小值x,那么对于每一条边e 一定有:

e.w+s[e.from]-s[e.to]>=x   <==>    s[e.to]-s[e.from]<=e.w-x  ;

其实就是每条边的权重都减小x;

剩下的就是开心的差分啦~~

貌似比较简单,但是wa了6次,主要是因为判定负权回路的条件是进队次数达到n+1次(而不是n次)!!

代码:

#include<cstdio>    
#include<iostream>  
#include<cstring>    
#include<queue>    
#include<vector>
#include<cstdlib>     
  
#define LL long long    
#define CLEAR(XXX) memset((XXX),0,sizeof(XXX))  
using namespace std;   
    
const int maxn=500+5,maxm=5000+5,inf=1e9;    
    
int m,n;
inline void _read(int &x){    
    char ch=getchar(); bool mark=false;    
    for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;    
    for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';    
    if(mark)x=-x;    
}    
struct Edge{    
    int from,to,w;    
    Edge(int from,int to,int w):from(from),to(to),w(w){}  
};      
struct SPFA{    
    int  n,m;    
    vector<Edge> edge;    
    int last[maxm],next[maxm];    
    LL dist[maxn];    
    int cnt[maxn];    
    bool vis[maxn];    
    void init(int n){    
        this->n = n;    
        m=0;    
        CLEAR(last); CLEAR(next);    
        edge.clear();    
        edge.push_back(Edge(0,0,0));    
    }    
    void add_edge(int from,int to,int dist){    
        edge.push_back(Edge(from,to,dist));    
        m=edge.size()-1;    
        next[m]=last[from];    
        last[from]=m;    
    }    
    bool solve(int s,int p){    
        int i;    
        CLEAR(vis); CLEAR(cnt);      
        for(i=1;i<=n;i++) dist[i]=inf;    
        dist[s]=0;  
        vis[s]=true;cnt[s]++;    
        queue <int> q;    
        q.push(s);    
        while(!q.empty()){    
            int x=q.front();    
            q.pop();vis[x]=false;  //及时修改标记   
            for(i=last[x];i;i=next[i]){    
                Edge e=edge[i];  
				e.w-=p;  
                if(dist[e.from]+e.w<dist[e.to]){    
                    dist[e.to]=dist[e.from]+e.w;    
                    if(!vis[e.to]){    
                        cnt[e.to]++;  //统计入队次数,判断负权回路 注意是n+1次!!  
                        if(cnt[e.to]==n+1)return false;    
                        q.push(e.to) ;    
                        vis[e.to]=true;    
                    }    
                }     
            }    
        }    
		return true;    
    }    
    void answer(){    
        for(int i=1;i<=n;i++)    
            if(dist[i]>=inf)printf("NoPath\n");    
            else printf("%I64d\n",dist[i]);    
    }    
}; 
SPFA solver;   
int main(){    
  	int i,x,y,d,l,r,ans=0;
  	while(cin>>n>>m){
  		solver.init(n);
  		for(i=1;i<=m;i++){
  			_read(x);_read(y);_read(d);
  			solver.add_edge(x,y,d);
		  }
		for(i=1;i<=n;i++)solver.add_edge(0,i,0);
		l=1;r=10001;
		if(!solver.solve(0,1)){
			 puts("No Solution");continue;
		}
		if(solver.solve(0,r)) {
			puts("Infinite");continue;
		}
		while(l<=r){
			int mid=(l+r)>>1;
			//w[x]+s[from]-s[to]>=mid; <=> s[to]-s[from]<=w[x]-mid; 
			if(solver.solve(0,mid)) l=mid+1,ans=max(ans,l);
			else r=mid-1;
		}
		printf("%d\n",r);
  	}
  	return 0;
}    
     


UVA - 11478 Halum二分答案+spfa】 题目链接:https://cn.vjudge.net/problem/UVA-11478 这道题有两点收获。 1,stack的spfa的确要比queue的spfa快很多,如果发现queue的spfa超时的话,可以试试用stack。 2,之前的spfa模板给记错了,我以为松弛的次数是边的数目,今天才发现松弛的次数应该是点的数目,在搞错这个的情况下,我用stack就AC了,之前一直T,我是和别人... 阅读详情

相关推荐

例题5.16 Halum操作 UVa11478

1.题目描述:点击打开链接 2.解题思路:本题利用BellmanFord算法+二分解决。本题要求执行完一系列Halum操作后,可以让边权的最小值非负且尽量大。自然想到可以用二分法来解决。假设答案是x。即问题转化为所有边的边权经过操作后都大于等于x。然而这里有一个问题,我们根本不知道应该怎么选取相应的v,d,使得可以达到这个目标。但是仔细观察后就可以注意到一个特点:不同的操作影响是相互独立的,即影

Skyline 453

uva11478 Halum

微微发光的传送门 题目中给了一种操作,就是制定一个d,和一个结点v,把所有以v为终点的边的权值减少d,把所有以v为起点的边权增加d,然后使最小的边权最大。 看到最小最大这类的字眼,首先想到的就是二分答案,假设每一条边的边权都不小于x,对于一条边,是从a指向b的,然后假定sum(a)和sum(b)分别是左右于a和b上的所有操作的d的和,那么对于这条边,它的权重就应该是w+sum(a)-sum(b

浅雨歌 670

Halum UVA - 11478 差分约束

Halum UVA - 11478 差分约束 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 复制 2 1 1 2 10 2 1 1 2 -10 3 3 1 2 4 2 3 2 3 1 5 4 5 2 3 4 4 2 5 3 4 2 3 1 0 1 2 -1 输出样例#1: 复制 Infinite Infinite...

loooooog的博客 159

UVA11478 Halum 解题报告【图论】【二分答案】【SPFA】【差分约束系统

UVA 11478

中国计算机学会成都七中(高新校区)委员会委员活动室 523

Uva 11478 Halum差分约束系统 + 二分

题意:一个有向图,每条边有权值,你可以每次选择一个点v和一个整数d,所有以v为起点的边的权值增加d,以v为终点的权值减小d,问是否能让所有边权为正数 思路:二分答案ans,设有边(a, b),对a操作的总和为sum(a),对b操作的总和为sum(b),w(a, b)变为了w(a, b) + sum(a) - sum(b),可知对所有边:w(a, b) + sum(a) - sum(b)

hnust_Derker的博客 342

UVA 11478 Halum差分约束系统+Bellman-Ford)

 题意:给定一个有向图,每条边都有一个权值。每次你可以选择一个结点v和一个整数d,把所有以v为终点的边的权值减小d,把所有以v为起点的边的权值增加d,最后让所有边的权值的最小值大于零且尽量大。 ps:lrj的书上有个坑,说上说非负,其实原题说要大于0.....wa了好几发 分析:因为不同的操作互不影响,因此可以按任意顺序实施这些操作。另外,对于同一个点的多次操作可以合并,因此可以令sum

GODSPEED 1053

Uva 11478 - Halum二分+差分约束)

题目链接 https://vjudge.net/problem/UVA-11478 【题意】 给定一张带权有向图,每次你可以选择一个结点v和一个整数d,把所有以v为终点的边的权值减少d,把所有以v为起点的边的权值增加d,最后要让所有边权最小值大于0且尽量大。对于每组数据输出边权最小值的最大值,如果无法让所有边权都大于0则输出”No Solution”,如果边权最小值可任意大,输出”Infini...

Change the world by program. 281

UVA11478 [Halum] 二分答案+SPFA差分约束系统

UVa11478 二分答案 SPFA 差分约束系统

Venishel的博客 323

uva 11478 Halum(图论-差分约束)

uva 11478 Halum(图论-差分约束) 题目大意: 你可以给每个点的入边加一个值和出边加一个值,问你最小的边权最大是多少? 解题思路: 用二分枚举答案假设为x,那么 w(a,b)+sum[a]-sum[b]>=x,这些不等式构成了差分约束系统

炒饭君的博客 1343

uva11478 - Halum 二分+差分约束

You are given a directed graph G(V,E) with a set of vertices and edges. Each edge (i,j) that connects some vertex i to vertex j has an integer cost associated with that edge.   Define the operation

467

UVA 11478 - Halum 差分约束

给定一个有向图,每条边都有一个权值,每次你可以选择一个结点v和整数d,把所有以v为终点的边权值减少d,把所有以v为起点的边权值增加d,最后要让所有的边权值非负且最大。

细语呢喃 2172

UVA 11478 Halum 二分+差分约束+SPFA

题意: 给定一个有向图,每条边都有一个权值,每次你可以选择一个结点v和整数d,把所有以v为终点的边权值减少d,把所有以v为起点的边权值增加d,最后要让所有的边权值非负且最大,并输出最小值最大化。 题解: 这道差分约束题可以这样想,因为要找最小中的最大,而又没给值我们进行操作,让我们自由发挥,那么我们是不是可以想到用在茫茫数海中寻找一个符合条件的算法~二分法,找到答案,因为最终我

Start_to_crazy的博客 315

UVA 11478 Halum(用bellman-ford解差分约束)

对于一个有向带权图,进行一种操作(v,d),对以点v为终点的边的权值-d,对以点v为起点的边的权值+d。现在给出一个有向带权图,为能否经过一系列的(v,d)操作使图上的每一条边的权值为正,若能,求最小边权的最大值。 不得不说,图论与动态规划的产物实在是神奇!! 1、既然是“最小值最大”问题,容易想到二分答案。 2、抽象出数学模型。这个在《训练指南》里写得已经很详细,鄙人还是以自己的...

aizhengcuo9261的博客 226

uva11478(差分约束,spfa求负环)

UVA - 11478 Halum (最短路应用+二分) Description   Problem H Halum Time Limit : 3 seconds     You are given a directed graph G(V,E) with a set of vertices and edges.

martinue 535

UVA 11478 Halum 差分约束系统 + 二分答案

设sum(u)为在结点u上的全部操作叠加(操作顺序无影响) 则原边w(a,b)变为w(a,b)+sum(a)-sum(b) 二分答案x,则w(a,b)+sum(a)-sum(b)>=x,即sum(b)-sum(a)<=w(a,b)-x 差分约束系统 构图用SPFA判断是否有解。 //#pragma comment(linker, "/STACK:1024000000,...

weixin_34177064的博客 122

UVA11478Halum (最短路解差分约束)

题目: Sample Input2 11 2 102 11 2 -103 31 2 42 3 23 1 54 52 3 44 2 53 4 23 1 01 2 -1Sample OutputInfiniteInfinite31 题意:   给定一个有向图,每条边都有一个权值。每次你可以选择一个结点v和一个整数d,把所有以v为终点的边的权值减小d,把所有以v为起点的边的权值...

weixin_30856965的博客 82
上一篇: 差分超级坑题--nkoj2112(scoi2011)
下一篇: poj——1275 Cashier Employment 差分约束系统
INCINCIBLE
博客等级 码龄11年 31粉丝 195原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值