zoukankan      html  css  js  c++  java
  • UVA 11478(差分约束 + 二分)

    题意:

    给定一个有向图,每条边都有一个权值,每次你可以选择一个结点和一个整数的,把所有以v为终点的边的权值减去d,

    把所有以v为起点的边的权值加上d

    最后要让所有边的权的最小值非负且尽量大

    代码

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int N = 1e3;
    const int inf  = 0x3f3f3f3f;
    int dist[N],inq[N],cnt[N];
    struct node
    {
        int v,w;
        node(int v,int w):v(v),w(w) {};
    };
    vector<node> G[N];
    void init(int n)
    {
        for(int i = 0; i<=n; i++) G[i].clear();
    }
    bool spfa(int n)
    {
        queue<int> q;
        q.push(0);
        memset(inq,0,sizeof(inq));
        memset(cnt,0,sizeof(cnt));
        memset(dist,inf,sizeof(dist));
        dist[0] = 0;
        inq[0] = 1;
        cnt[0] = 1;
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            inq[u] = 0;
            for(int i = 0; i<G[u].size(); i++)
            {
                int v = G[u][i].v, w= G[u][i].w;
                if(dist[v]>dist[u] + w)
                {
                    dist[v] = dist[u] + w;
                    if(!inq[v]) q.push(v),inq[v] = 1;
                    if(++cnt[v]>n) return true;
                }
            }
        }
        return false;
    }
    bool test(int mid,int n)
    {
        for(int i = 1; i<=n; i++)
            for(int j = 0; j<G[i].size(); j++)
                G[i][j].w -=mid;
        int ret = spfa(n);
        for(int i = 1; i<=n; i++)
            for(int j = 0; j<G[i].size(); j++)
                G[i][j].w +=mid;
        return ret;
    }
    int main()
    {
        int V,E;
        while(~scanf("%d%d",&V,&E))
        {
            init(V);
            int ub = 0;
            int u ,v ,w;
            for(int i = 0; i<E; i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                G[u].push_back(node(v,w));
                ub = max(w,ub);
            }
            for(int i = 1; i<=V; i++)
                G[0].push_back(node(i,0));
            int L = 1, R = ub;
            if(test(L,V)) puts("No Solution");
            else if(!test(ub+1,V)) puts("Infinite");
            else
            {
                while(L<R)
                {
                    int mid = L + (R -L)/2;
                    if(test(mid,V)) R = mid ;
                    else  L = mid + 1;
                }
                printf("%d
    ",L-1);
            }
        }
        return 0;
    }
    

     

  • 相关阅读:
    移动端触摸右侧菜单栏,页面内容对应项滚动到最上方
    swiper使用中一些点的总结
    javaScript正则表达式入门
    javaScript之数组操作方法(一)
    初识vue
    焦点控制切换和轮播
    文本内容只显示两行,然后加...
    图片父容器高度不定的图片垂直居中
    css3图片垂直居中
    【C#】两个list根据某个元素比较差集
  • 原文地址:https://www.cnblogs.com/jiachinzhao/p/4937583.html
Copyright © 2011-2022 走看看