hdu2883 网络流 离散化 建图

来源:互联网 发布:ubuntu给予文件夹权限 编辑:程序博客网 时间:2024/05/21 19:47

题解转自大佬:http://blog.csdn.net/u013480600/article/details/38984057
题意:
给定n个顾客,第i号顾客在si到达,点了ni个羊肉串,每个羊肉串需要ti个时间烤好。顾客想要在ei得到,一个烤炉只烤m串。问你是否能满足所有顾客的要求?能的话输出“Yes”,否则输出“No”。
注意:这ni个羊肉串可以被分开来考,一个单独的羊肉串也能分开烤(比如一个单独的羊肉串需要ti时间,我们把它分成ti份同时烤的话,那么一个羊肉串可以在1个单位时间内拷完)
注意:每个顾客的任务必须在(si,ei]半开半闭的区间内完成.
分析:
本题与HDU3572有点类似:
http://blog.csdn.net/u013480600/article/details/38962999
其实本题的本质就是HDU3572的思想,每个顾客其实提出的是需要ni*ti个单位时间任务(甚至可以在1个时刻同时完成,因为一串羊肉串都可以在1个时刻烤完),但是你每个时间只能提供m个单位时间做任务. 但是这个题目的时间点覆盖1到100W,明显不能再把每个单独的时间看成一个点了,所以这题要把每个不重叠的子时间区间看成一个点.
首先读入所有任务的开始时间s[i]和结束时间e[i],然后对这些时间点排序,去重,得到cnt个时间点,然后我们就能得到cnt-1个半开半闭的子时间区间(前后两个子区间边界不重叠,且所有区间连起来正好覆盖了原来的整个大时间区间,该大时间区间也是半开,半闭的).
建图: 源点s编号0, n个任务编号1到n, cnt-1个区间编号n+1到n+cnt, 汇点t编号n+cnt+1.
源点到每个任务i有边(s,i,ni*ti)
每个时间区间j到汇点有边(j,t, 该区间覆盖的单位时间点数)
如果任务i包含时间区间j,那么有边(i,j,INF)
求最大流,看最大流 是否== 所有任务需要的单位时间之和即可.

代码:

#include <bits/stdc++.h>using namespace std;const int INF  = 0x3f3f3f3f;const int maxn = 608;const int Mod  = 1e9 + 7;#define ll       long long#define mem(x,y) memset(x,y,sizeof(x))#define IO       ios_base::sync_with_stdio(0), cin.tie(0);inline ll gcd(ll a, ll b) {return a % b == 0 ? b : gcd(b, a % b);}inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}inline ll quick_pow(ll x, int k) {ll ans = 1; while (k) { if (k & 1) ans = (ans * x) % Mod; x = x * x % Mod;  k >>= 1; } return ans;}int dep[maxn];struct Node {    int  v, w, re_id;    Node() {};    Node(int a, int b, int c) {        v = a, w = b, re_id = c;    }};vector<Node> node[maxn];void addEdge(int u, int v, int w) {    node[u].push_back(Node(v, w, node[v].size()));    node[v].push_back(Node(u, 0, node[u].size() - 1));}int bfs(int s, int t) {    queue<int> Q;    mem(dep, -1);    dep[s] = 0;    Q.push(s);    while (!Q.empty()) {        int u = Q.front();        Q.pop();        for (int i = 0; i < node[u].size(); i++) {            int v = node[u][i].v;            if (node[u][i].w > 0 && dep[v] == -1) {                dep[v] = dep[u] + 1;                Q.push(v);            }        }    }    return dep[t] != -1;}int  dfs(int s, int t, int f) {    if (s == t || f == 0) return f;    int sumf = 0;    for (int i = 0; i < node[s].size(); i++) {        int v = node[s][i].v;        if (node[s][i].w > 0 && dep[v] == dep[s] + 1) {            int tmp = dfs(v, t, min(f, node[s][i].w));            if (tmp > 0) {                node[s][i].w -= tmp;                node[v][node[s][i].re_id].w += tmp;                sumf += tmp, f -= tmp;            }        }    }    if (sumf == 0) dep[s] = -1;    return sumf;}int dinic(int s, int t) {    int ans = 0;    while (bfs(s, t))  ans += dfs(s, t, INF);    return ans;}set<int> st;int main() {    int N, M, s[202], need, e[202], t, ss = 0, tt = 602;    while (scanf("%d%d", &N, &M) != EOF) {        for (int i = 0; i < maxn; i++) node[i].clear();        st.clear();        int mx = 0, sum = 0;        for (int i = 1; i <= N; i++) {            scanf("%d%d%d%d", &s[i], &need, &e[i], &t);            sum += need * t;            addEdge(ss, i, need * t);            st.insert(s[i]);            st.insert(e[i]);        }        set<int>::iterator it = st.begin(), it2 = st.begin();        it2++;        for (int i = 1; i < st.size(); i++, it++, it2++) {            int b = *it2, a = *it;            addEdge(i + N, tt, (b - a)*M);            for (int j = 1; j <= N; j++) {                if (s[j] <= a && e[j] >= b)                    addEdge(j, i + N, INF);            }        }        if (dinic(ss, tt) == sum ) printf("Yes\n");        else printf("No\n");    }}
原创粉丝点击