Uvaoj 11248 Frequency Hopping(Dinic求最小割)

简介:

题意:1到n节点(节点之间有一定的容量),需要流过C的流量,问是否可以?如果可以输出possible, 否则如果可以扩大任意一条边的容量
可以达到目的,那么输出possible option:接着输出每一条可以达到目的的边(按升序),再否则输出not possible
思路:先求一次最大流,如果流量至少为C,则直接输出possible,否则需要修改的弧一定在最小割里!
接着吧这些弧(最小割里的)的容量设为无穷大,然后在求最大流,看最大流的流量能否满足是C即可,如果满足了,那就把这一条边记录下来

分析:最大流的程序没有必要完全的执行完毕,知道当前的流量>=C那么就可以中止最大流的程序!
还有就是第一次的最大流程序如果没有找到>=C的最大流,那么此时的流量留着,下一次在最小割里扩容的时候,总是接着第一次Dinic的流量
继续寻找....


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#define N 105
#define INF 2000000005
using namespace std;

struct EDGE{
    int u, v, nt, cap;
    bool flag;
    bool vis;
    EDGE(){}
    EDGE(int u, int v, int nt, int cap, bool flag):u(u), v(v), nt(nt), cap(cap), flag(flag){}
};

struct node{
    int x, y;
    node(){}
    node(int x, int y) : x(x), y(y){}
};

int pos[10005];

node ans[10005];
int preCost[20005];
int vis[20005];
int p[20005];
int pcnt;
int cnt;

vector<EDGE>g;
int first[N];

int d[N];
int n, e, c;

void addEdge(int u, int v, int c){
    g.push_back(EDGE(u, v, first[u], c, true));
    first[u] = g.size() - 1;
    g.push_back(EDGE(v, u, first[v], 0, false));
    first[v] = g.size() - 1;
}

bool bfs(){
    memset(d, 0, sizeof(d));
    d[1] = 1;
    queue<int>q;
    q.push(1);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i = first[u]; ~i; i = g[i].nt){
            int v = g[i].v;
            if(!d[v] && g[i].cap > 0){
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    if(d[n] == 0) return false;
    return true;
}

bool cmp(node a, node b){
    if(a.x == b.x)
         return a.y < b.y;
    return a.x < b.x;
}

int leave;

int dfs(int u, int totf){
    int flow = 0;
    if(u ==n || totf==0) return totf;
    for(int i = first[u]; ~i; i = g[i].nt){
        int v = g[i].v;
        if(d[v] == d[u] + 1 && g[i].cap > 0){
            int ff  = dfs(v, min(totf-flow, g[i].cap));
            if(ff > 0){
                if(!vis[i]){
                    p[pcnt++]=i;
                    preCost[i] = g[i].cap;
                    vis[i] = 1;
                }
                g[i].cap -= ff;

                if(!vis[i^1]){
                    p[pcnt++]=i^1;
                    preCost[i^1] = g[i^1].cap;
                    vis[i^1] = 1;
                }
                g[i^1].cap += ff;
                flow += ff;
                
                if(flow >= leave){
                    flow = leave;
                    return flow;
                }

                if(totf == flow) break;
            }
            else d[v] = -1;
        }
    }
    return flow;
}

bool Dinic(){
    leave = c;
    while(bfs()){
        leave -= dfs(1, INF);
        if(leave == 0) break;
    }
    if(leave == 0) return true;
    return false;
}
 


int main(){
    int cas = 0;
    while(scanf("%d%d%d", &n, &e, &c)){
        if(!n) break;
        memset(first, -1, sizeof(first));
        g.clear();
        cnt = 0;
        while(e--){
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            addEdge(x, y, z);
        }
        printf("Case %d: ", ++cas);//这一块差点没有把我气死...居然有一个空格,没有看清楚啊...一直PE.
     
        if(n==1){
            printf("possible\n");
            continue;
        }

        if(Dinic())  printf("possible\n");
        else{
            int len = g.size();
            for(int i=0; i<len; ++i)
                if(g[i].cap == 0 && g[i].flag)
                    pos[cnt++] = i;//得到最小割
            int cc = leave;//第一次Dinic之后,还剩下多少的流量需要流过
            int ret = 0;
            for(int i=0; i<cnt; ++i){
                c = cc;//新的需要流过的流量
                pcnt = 0;
                g[pos[i]].cap = INF;
                memset(vis, 0, sizeof(vis));
                if(Dinic())//如果增广成功,那么这条最小割满足
                       ans[ret++] = node(g[pos[i]].u, g[pos[i]].v);
                for(int j=0; j<pcnt; ++j)
                    g[p[j]].cap = preCost[p[j]];//将Dinic中所经过的边的值恢复成第一次Dinic之后的值!
                g[pos[i]].cap = 0;
            }
            if( ret > 0 ){
                sort(ans, ans+ret, cmp);
                printf("possible option:(%d,%d)", ans[0].x, ans[0].y);
                for(int i=1; i<ret; ++i)
                    printf(",(%d,%d)", ans[i].x, ans[i].y);
                printf("\n");
            }
            else printf("not possible\n");
        }
    }    
    return 0;
}


目录
相关文章
|
C++
hackerrank challenges median
只能说这题我想多了,使用普通的插入排序完全可以解决这道题,在查找的时候用二分加快查找速度。 正确解题报告 这道题的关键在于,不能用int,因为两个int相加可能会越界!因为这个WA了好多遍。所以改用long long。 对double,使用math.h中的函数ceil(double)可以取整,根据ceil(v) == v的结果可以判断v是否是整数。
50 0
|
机器学习/深度学习 人工智能 自然语言处理
Term Frequency-Inverse Document Frequency
TF-IDF算法全称是&quot;Term Frequency-Inverse Document Frequency&quot;,可译为&quot;术语频率-文档逆向频率&quot;。
112 4
|
算法 Serverless 语音技术
Mel-Frequency Cepstral Coefficients,简称 MFCCs
频率倒谱系数(Mel-Frequency Cepstral Coefficients,简称 MFCCs)是一种在语音信号处理中常用的特征提取方法。MFCCs 是通过对语音信号进行傅里叶变换
133 1
paraforme支持speech_noise_threshold吗?
请问:speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch 这个模型支持设置 speech_noise_threshold 这个参数吗 ? vad 本身是支持的,但对这个集成的模型好像不起作用? 如果支持,应该如何正确地设置呢 ? 如果不支持,那该模型有没有什么方法可以过滤掉背景噪声? 经常会有背景噪声被识别出文字
48 0
|
机器学习/深度学习 自然语言处理 算法
词频-逆文档频率(Term Frequency-Inverse Document Frequency,
词频-逆文档频率(Term Frequency-Inverse Document Frequency,简称 TF-IDF)是一种统计方法,用以评估一个词对于一个文本或一组文本的重要性。
496 3
|
编解码 语音技术
采样率(sample rate)
采样率(sample rate)
1030 0
【1096】Consecutive Factors (20 分)
【1096】Consecutive Factors (20 分) 【1096】Consecutive Factors (20 分)
123 0
|
Windows
1029. Median (25)
#include #include #include #include using namespace std; int main(){ long long n, t; cin >> n; ...
896 0