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 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 Sample Output    
 

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


Infinite
Infinite
3
1



   
 

Problem Setter: Md. Mahbubul Hasan
Next Generation Contest 5


WA了半个礼拜的题终于找到错在哪了==

先说题意:对于给定有向图,定义一种操作:对于选定的某一点,进入这个点的所有边权都减去d,从这个点出去的所有边权都加上d。经过一系列的操作,使得所有边权的最小值达到最大,需保证这个最值是正数==

既然是差分约束,需要记得把点当做最短路的点假设每个点都有一个点权sum(a),而w(a,b)+sum(a)-sum(b)>=x,x是所有边权的最小值,把边权sum放到等号右边,就构成了差分约束的不等式组,,保证不出现负环的spfa就是最大的x求得的。

再说我错在哪了,对于这个题来说,要人为加一个超级源点,(就像网络流一样,没有固定的源点汇点,就要人为添加)我就是因为没有这句话还觉得自己二分或者模板错了orz 要是不想加源点,spfa模板最开始push的点就是1-n都加进去,dist[]都是0

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int inf=0x3f3f;
const int maxn=505;
int n,m;
struct Edge
{
    int v,cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[maxn];
void addedge(int u,int v,int w)
{
    E[u].push_back(Edge(v,w));
}
bool vis[maxn];
int cnt[maxn];
int dist[maxn];
bool spfa(int start,int n)
{
    memset(vis,false,sizeof(vis));
    memset(dist,inf,sizeof(dist));
    vis[start]=true;
    dist[start]=0;
    queue<int>que;
    while(!que.empty()) que.pop();
    que.push(start);
    memset(cnt,0,sizeof(cnt));
    cnt[start]=1;
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        vis[u]=false;
        for(int i=0;i<E[u].size();i++)
        {
            int v=E[u][i].v;
            if(dist[v]>dist[u]+E[u][i].cost)
            {
                dist[v]=dist[u]+E[u][i].cost;
                if(!vis[v])
                {
                    vis[v]=true;
                    que.push(v);
                    if(++cnt[v]>n) return false;
                }
            }
        }
    }
    return true;
}
bool judge(int x)
{
   // cout<<"rrr"<<endl;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<E[i].size();j++)
            E[i][j].cost-=x;
    }
    bool flag=spfa(0,n);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<E[i].size();j++)
            E[i][j].cost+=x;
    }
    return flag;
}
    int main()
    {
        //freopen("cin.txt","r",stdin);
       // int cas=1;
       // scanf("%d",&t);
        while(~scanf("%d%d",&n,&m))
        {
           // printf("Case #%d: ",cas++);
            for(int i=0;i<=n;i++) E[i].clear();
        //    memset(head,-1,sizeof(head));
            int l=1,mid,r=-inf;
            while(m--)
            {
                int a,b;
                int c;
                scanf("%d%d%d",&a,&b,&c);
                addedge(a,b,c);
                if(c>r)r=c;
            }
            for(int i=1;i<=n;i++)addedge(0,i,0);
          //  cout<<"rrr"<<endl;
           // printf("r=%d\n",r);
            if(judge(r))
            {
                printf("Infinite\n");
                continue;
            }
            else if(!judge(1))
            {
                puts("No Solution");
                continue;
            }
            int ans;
            while(l<=r)
            {
                mid=(l+r)/2;
               // cout<<mid<<endl;
               // printf("l=%d,mid=%d,r=%d    ",l,mid,r);
                if(judge(mid)) ans=mid,l=mid+1;
                else {r=mid-1;}
               // printf("l=%d,mid=%d,r=%d,ans=%d\n",l,mid,r,ans);
            }
            printf("%d\n",ans);
        }
        return 0;
    }


全部评论

相关推荐

09-13 17:25
亲切的00后在笔试:我也遇到了,所以我早他一步查看图片
点赞 评论 收藏
分享
天降大厂offer:你是我见过最美的牛客女孩
点赞 评论 收藏
分享
10-23 16:33
门头沟学院 Java
本人某中9本科,成绩中等,目前没科研没实习,目前后端学到了javaWeb,开始没定好方向,在学国外课程,走工程路线起步有点晚了,到这个时间点了还在学JavaWeb,顿感迷茫,不知道是坚持走下去还是寒假去准备考研。考研这个路弄得我还是心痒痒的,因为从众考研的人也不在少数,所以会有这方面的心理安慰吧,就是“不行我可以去考研啊”,而且意味着三年的缓冲,为了复试还有积攒经验美化简历,其实现在也可以去申入实验室打杂;就业可能意味着多些工作经验,工程岗应该到后面还是经验大于学历?还是有点迷茫了,求助好心人有无路线启发
千千倩倩:同27给点建议,现在这个时间点可以快速看完外卖和点评,不用跟着敲,但一定要在看的时候总结每个部分的整个业务流程,对其中的实现有一个大概的印象。然后直接开始看八股,刷算法。八股和算法最好还是在项目学习中穿插着看。如果计算机基础,算法这些基础好,加上每天刻苦学习,两周可以达到勉强能面试的水平,到时候就直接海投中小厂,在约面和面试的过程中不断巩固知识。没找到实习也没关系,就当积累经验。再沉淀一波直接明年三月开始投暑期,毕竟是9本,总是有面试机会的,只要你这三个月不懈怠,面试发挥得一定不错,只要拿到一个中,大厂暑期实习,秋招就有竞争力了。总得而言,现在还有机会,但是时间非常紧张,需要你结合自己情况考虑,共勉
你会选择考研还是直接就业
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务