網路流小結

2020-08-10 01:06:48
  • hdu 3572 Task Schedule
    題意:
    現在你有m個機器,n個任務,每個任務有三個屬性p,s,e,表示只能在[p,e]區間內花s的時間做完這個任務,一個機器一個時間只能做一個任務,一個任務一個時間只能被一個機器做,現在問你能不能完成全部的任務。
    n,m <= 500
    1 <= p,s,e <= 500
    思路:
    設0是源點,1~500是機器,501~1000是天數,1100是匯點,假設任務i三個屬性p,s,e,源點連一條容量s的邊到點 i,然後點 i 分別向每個[500+p, 500+e]的頂點連容量爲1的邊,最後501~1000向匯點連一條容量爲1的邊,跑個最大流,如果最大流等於所有任務s之和就是YES,否則就是NO。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3000;   //點數
const int INF = 0x3f3f3f3f;
int tc,n,m;
struct Edge{
    int from, to, cap, flow;  //如果要開ll的話,這邊也要開ll
    Edge(int u, int v, int c, int f)
        : from(u), to(v), cap(c), flow(f) {}
};
struct Dicnic {
    #define Type int
    int n, m, s, t;        //節點數,邊數(包括反向弧),源點編號和匯點編號
    vector<Edge> edges;    //邊表。edge[e]和edge[e^1]互爲反向弧
    vector<int> G[maxn];   //鄰接表,G[i][j]表示節點i的第j條邊在e陣列中的編號
    bool vis[maxn];        //BFS使用
    Type d[maxn];           //從起點到i的距離
    int cur[maxn];         //當前弧下標
    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; ++i) G[i].clear();
        edges.clear();
    }
    void addEdge(int from, int to, int cap) {
        edges.emplace_back(Edge(from, to, cap, 0));
        edges.emplace_back(Edge(to, from, 0, 0));
        m = int(edges.size());
        G[from].emplace_back(m-2);
        G[to].emplace_back(m-1);
    }
    bool BFS() {
        memset(vis, 0, sizeof(vis));
        memset(d, 0, sizeof(d));
        queue<int> q;
		while (!q.empty()) q.pop();
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = 0; i < int(G[x].size()); ++i) {
                Edge &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    Type DFS(int x, Type a) {
        if (x == t || a == 0) return a;
        Type flow = 0, f;
        for (int &i = cur[x]; i < int(G[x].size()); ++i) { //從上次考慮的弧
            Edge &e = edges[G[x][i]];
            if (d[x]+1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {
                e.flow += f;
                edges[G[x][i]^1].flow -= f;
                flow += f;
                a -= f;
                if (a == 0) break;
            }
        }
        return flow;
    }
    Type Maxflow(int s, int t) {
        this->s = s; this->t = t;
        Type flow = 0;
        while (BFS()) {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, INF);
        }
        return flow;
    }
    #undef Type
}dicnic;
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    cin>>tc;
    int kase=1;
    while(tc--){
        int sum=0;
        cin>>n>>m;
        dicnic.init(1300);
        for(int i=1; i<=n; ++i){
            int p,s,e;
            cin>>p>>s>>e;
            sum+=s;
            dicnic.addEdge(0,i,s);
            for(int j=500+p; j<=500+e; ++j) dicnic.addEdge(i,j,1);
        }
        for(int i=501; i<=1000; ++i) dicnic.addEdge(i,1100,m);
        int all=dicnic.Maxflow(0,1100);
        cout<<"Case "<<kase++<<": ";
        if(all==sum) cout<<"Yes"<<'\n';
        else cout<<"No"<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}