1. 程式人生 > >無法拯救我的菜----焦作網路賽 F. Modular Production Line

無法拯救我的菜----焦作網路賽 F. Modular Production Line

poj3680原題,資料都一樣,是最小費用最大流摸板題 轉載:https://blog.csdn.net/zhou_yujia/article/details/52411251 先看一下poj3680: 離散化所有區間的端點,把每個端點看做一個頂點,建立附加源S匯T。 1、從S到頂點1(最左邊頂點)連線一條容量為K,費用為0的有向邊。 2、從頂點2N(最右邊頂點)到T連線一條容量為K,費用為0的有向邊。 3、從頂點i到頂點i+1(i+1<=2N),連線一條容量為無窮大,費用為0的有向邊。 4、對於每個區間[a,b],從a對應的頂點i到b對應的頂點j連線一條容量為1,費用為區間長度的有向邊。 求最大費用最大流,最大費用流值就是最長k可重區間集的長度。 這個問題可以看做是求K條權之和最大的不想交路徑,每條路徑為一些不相交的區間序列。由於是最大費用流,兩條路徑之間一定有一些區間相交,可以看做事相交部分重複了2次, 而K條路經就是最多重複了K次。最簡單的想法就是把區間排序後,不相交的區間之間連線一條邊,由於每個區間只能用一次,所以要拆點,點內限制流量 在這裡插入圖片描述

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int MAXN = 405;
const int MAXM = 100005;

typedef struct Node{
    int s,to,next,capacity,value;
}Node;

int n,k;
int ecnt;
Node node[MAXM];
int pre[MAXN];
int head[MAXN];
int dis[MAXN];
bool vis[MAXN];
int u[MAXN],v[MAXN],w[MAXN];
vector<int>ve;
map<int,int>mp;

void init()
{
    ecnt = 0;
    memset(head,-1,sizeof(head));
    memset(node,0,sizeof(node));
}

void addEdge(int u,int v,int w,int c)
{
    node[ecnt].to = v;
    node[ecnt].s = u;
    node[ecnt].capacity = c;//流量
    node[ecnt].value = w;//路徑長度是費用
    node[ecnt].next = head[u];
    head[u] = ecnt++;
    node[ecnt].to = u;
    node[ecnt].s = v;
    node[ecnt].capacity = 0;//流量
    node[ecnt].value = -w;//路徑長度是費用
    node[ecnt].next = head[v];
    head[v] = ecnt++;
}

bool spfa(int s,int t,int nnum)
{
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    for(int i = 0;i <= nnum;++i)
    {
        dis[i] = inf;
    }
    queue<int>que;
    que.push(s);
    dis[s] = 0;
    vis[s] = true;
    while(!que.empty())
    {
        int temp = que.front();
        que.pop();
        vis[temp] = false;
        for(int i = head[temp];i + 1;i = node[i].next)
        {
            if(node[i].capacity)
            {
                int ne = node[i].to;
                if(dis[temp] + node[i].value < dis[ne]){
                    dis[ne] = dis[temp] + node[i].value;
                    pre[ne] = i;
                    if(!vis[ne]){
                        que.push(ne);
                        vis[ne] = true;
                    }
                }
            }
        }
//        for(int i = 0;i <= nnum;++i)
//            cout << dis[i] << " ";
//        cout << endl;
    }
    if(dis[t] == inf)
        return false;
    return true;
}

int getMincost(int s,int t,int nnum)
{
    int ans_flow = 0;
    int ans_cost = 0;
    int temp,minc;
    while(spfa(s,t,nnum))
    {
//        cout << 0 << endl;
        temp = t;
        minc = inf;
        while(pre[temp] != -1)
        {
            minc = min(node[pre[temp]].capacity,minc);
            temp = node[pre[temp]].s;
        }
        temp = t;
        while(pre[temp] != -1)
        {
            node[pre[temp]].capacity -= minc;
            int ss = pre[temp] ^ 1;
            node[ss].capacity += minc;
            temp = node[pre[temp]].s;
        }
        //cout << dis[t] << " " << minc << endl;
//        for(int i = s;i <= t;++i)
//        {
//            cout << dis[i] << " ";
//        }
//        cout << endl;
        ans_cost += dis[t] * minc;
    }
    return ans_cost;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        mp.clear();ve.clear();
        init();
        scanf("%d %d",&n,&k);
        for(int i = 1;i <= n;++i)
        {
            scanf("%d %d %d",&u[i],&v[i],&w[i]);
            ve.push_back(u[i]);
            ve.push_back(v[i]);
        }
        sort(ve.begin(),ve.end());
        ve.erase(unique(ve.begin(),ve.end()),ve.end());
        int s = 0;
        int t = ve.size() + 1;
        int len = ve.size();
        for(int i = 0;i < len;++i)
            mp[ve[i]] = i + 1;
        addEdge(s,1,0,k);
        addEdge(ve.size(),t,0,k);
        for(int i = 1;i < len;++i)
            addEdge(i,i + 1,0,inf);
        for(int i = 1;i <= n;++i)
            addEdge(mp[u[i]],mp[v[i]],-w[i],1);
        int res = getMincost(s,t,t);
        printf("%d\n",-1 * res);
    }
    return 0;
}

再看F這道題,區間變了而已,改為把A[i] - 1 放入陣列即可 注意:為什麼建邊把權值變為負呢,模板是最小費用最大流,每次用spfa找增廣路徑時,找到的是最小權值和,題意應該是找最大權值和

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int MAXN = 405;
const int MAXM = 100005;

typedef struct Node{
    int s,to,next,capacity,value;
}Node;

int n,k,m;
int ecnt;
Node node[MAXM];
int pre[MAXN];
int head[MAXN];
int dis[MAXN];
bool vis[MAXN];
int u[MAXN],v[MAXN],w[MAXN];
vector<int>ve;
map<int,int>mp;

void init()
{
    ecnt = 0;
    memset(head,-1,sizeof(head));
    memset(node,0,sizeof(node));
}

void addEdge(int u,int v,int w,int c)
{
    node[ecnt].to = v;
    node[ecnt].s = u;
    node[ecnt].capacity = c;//流量
    node[ecnt].value = w;//路徑長度是費用
    node[ecnt].next = head[u];
    head[u] = ecnt++;
    node[ecnt].to = u;
    node[ecnt].s = v;
    node[ecnt].capacity = 0;//流量
    node[ecnt].value = -w;//路徑長度是費用
    node[ecnt].next = head[v];
    head[v] = ecnt++;
}

bool spfa(int s,int t,int nnum)
{
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    for(int i = 0;i <= nnum;++i)
    {
        dis[i] = inf;
    }
    queue<int>que;
    que.push(s);
    dis[s] = 0;
    vis[s] = true;
    while(!que.empty())
    {
        int temp = que.front();
        que.pop();
        vis[temp] = false;
        for(int i = head[temp];i + 1;i = node[i].next)
        {
            if(node[i].capacity)
            {
                int ne = node[i].to;
                if(dis[temp] + node[i].value < dis[ne]){
                    dis[ne] = dis[temp] + node[i].value;
                    pre[ne] = i;
                    if(!vis[ne]){
                        que.push(ne);
                        vis[ne] = true;
                    }
                }
            }
        }
//        for(int i = 0;i <= nnum;++i)
//            cout << dis[i] << " ";
//        cout << endl;
    }
    if(dis[t] == inf)
        return false;
    return true;
}

int getMincost(int s,int t,int nnum)
{
    int ans_flow = 0;
    int ans_cost = 0;
    int temp,minc;
    while(spfa(s,t,nnum))
    {
//        cout << 0 << endl;
        temp = t;
        minc = inf;
        while(pre[temp] != -1)
        {
            minc = min(node[pre[temp]].capacity,minc);
            temp = node[pre[temp]].s;
        }
        temp = t;
        while(pre[temp] != -1)
        {
            node[pre[temp]].capacity -= minc;
            int ss = pre[temp] ^ 1;
            node[ss].capacity += minc;
            temp = node[pre[temp]].s;
        }
        //cout << dis[t] << " " << minc << endl;
//        for(int i = s;i <= t;++i)
//        {
//            cout << dis[i] << " ";
//        }
//        cout << endl;
        ans_cost += dis[t] * minc;
    }
    return ans_cost;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        mp.clear();ve.clear();
        init();
        scanf("%d %d %d",&m,&k,&n);
        for(int i = 1;i <= n;++i)
        {
            scanf("%d %d %d",&u[i],&v[i],&w[i]);
            ve.push_back(u[i] - 1);
            ve.push_back(v[i]);
        }
        sort(ve.begin(),ve.end());
        ve.erase(unique(ve.begin(),ve.end()),ve.end());
        int s = 0;
        int t = ve.size() + 1;
        int len = ve.size();
        for(int i = 0;i < len;++i)
            mp[ve[i]] = i + 1;
        addEdge(s,1,0,k);
        addEdge(ve.size(),t,0,k);
        for(int i = 1;i < len;++i)
            addEdge(i,i + 1,0,inf);
        for(int i = 1;i <= n;++i)
            addEdge(mp[u[i] - 1],mp[v[i]],-w[i],1);
        int res = getMincost(s,t,t);
        printf("%d\n",-1 * res);
    }
    return 0;
}