费用流写法TLE求助
查看原帖
费用流写法TLE求助
547908
NightTide楼主2024/10/11 11:24

刚学费用流,KM 算法和 Dinic 算法都试了下,但是只通过前面两个点,其他全部 TLE。求大佬帮忙看看

KM:

#include<bits/stdc++.h>
#define MAXN 200
#define MAXM 40000
#define INF 0x3f3f3f3f
using namespace std;
struct edge{
    int pre, to, flow, cost;
};
int n, cnt = 1, s, t, cst, flw, ban = -1;
int head[MAXN], dis[MAXN], dep[MAXN], cur[MAXN], flow[MAXN], pre[MAXN];
bool vis[MAXN];
edge e[MAXM], et[MAXM];
vector<pair<int, int>> res;
void add_edge(int u, int v, int f, int c){
    e[++cnt].pre = head[u]; e[cnt].to = v; e[cnt].flow = f; e[cnt].cost = c; head[u] = cnt;
    e[++cnt].pre = head[v]; e[cnt].to = u; e[cnt].flow = 0; e[cnt].cost = -c; head[v] = cnt;
}

bool SPFA(){
    memset(vis, 0, sizeof(vis));
    memset(dis, 0x3f, sizeof(dis));
    queue<int> q; q.push(s);
    vis[s] = true; dis[s] = 0; flow[s] = INF;
    while(!q.empty()){
        int now = q.front(); q.pop();
        vis[now] = false;
        for(int i = head[now]; i; i = e[i].pre){
            if(i == ban || (i ^ 1) == ban) continue;
            if(e[i].flow != 0 && dis[e[i].to] > dis[now] + e[i].cost){
                flow[e[i].to] = min(flow[now], e[i].flow);
                dis[e[i].to] = dis[now] + e[i].cost;
                pre[e[i].to] = i;
                if(!vis[e[i].to]){
                    q.push(e[i].to);
                    vis[e[i].to] = true;
                }
            }
        }
    }
    return !(dis[t] == INF);
}
void update(){
    int now = t;
    while(now != s){
        e[pre[now]].flow -= flow[t];
        e[pre[now] ^ 1].flow += flow[t];
        now = e[pre[now] ^ 1].to;
    }
    flw += flow[t];
    cst += dis[t] * flow[t];
}
int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            int x; scanf("%d",&x);
            add_edge(i, n + j, 1, -x);
        }
    }
    s = n * 2 + 1; t = s + 1;
    for(int i = 1; i <= n; i++) add_edge(s, i, 1, 0);
    for(int i = 1; i <= n; i++) add_edge(n + i, t, 1, 0);
    memcpy(et, e, sizeof(e));
    int final_f = 0, final_c = 0;
    while(SPFA()) update();
    final_c = cst;
    printf("%d\n",-final_c);
    for(int i = 2; i <= cnt; i += 2){
        if(e[i].to == s || e[i].to == t) continue;
        if(e[i ^ 1].to == s || e[i ^ 1].to == t) continue;
        ban = i; cst = 0; flw = 0;
        memcpy(e, et, sizeof(et));
        while(SPFA()) update();
        if(cst != final_c) res.push_back(make_pair(e[i ^ 1].to, e[i].to - n));
    }
    sort(res.begin(), res.end());
    for(int i = 0; i < res.size(); i++) printf("%d %d\n",res[i].first,res[i].second);
    return 0;
}

Dinic:

#include<bits/stdc++.h>
#define MAXN 200
#define MAXM 40000
#define INF 0x3f3f3f3f
using namespace std;
struct edge{
    int pre, to, flow, cost;
};
int n, cnt = 1, s, t, cst, ban = -1;
int head[MAXN], dis[MAXN], dep[MAXN], cur[MAXN];
bool vis[MAXN];
edge e[MAXM], et[MAXM];
vector<pair<int, int>> res;
void add_edge(int u, int v, int f, int c){
    e[++cnt].pre = head[u]; e[cnt].to = v; e[cnt].flow = f; e[cnt].cost = c; head[u] = cnt;
    e[++cnt].pre = head[v]; e[cnt].to = u; e[cnt].flow = 0; e[cnt].cost = -c; head[v] = cnt;
}
bool SPFA(){
    memset(dep, 0, sizeof(dep));
    memset(dis, 0x3f, sizeof(dis));
    queue<int> q; q.push(s);
    vis[s] = false; dis[s] = 0; dep[s] = 0;
    while(!q.empty()){
        int now = q.front(); q.pop(); vis[now] = false;
        for(int i = head[now]; i; i = e[i].pre){
            if(i == ban || (i ^ 1) == ban) continue;
            if(e[i].flow != 0 && dis[e[i].to] > dis[now] + e[i].cost){
                dis[e[i].to] = dis[now] + e[i].cost;
                dep[e[i].to] = dep[now] + 1;
                if(!vis[e[i].to]){
                    q.push(e[i].to);
                    vis[e[i].to] = true;
                }
            }
        }
    }
    return !(dis[t] == INF);
}
int dfs(int now, int lim){
    if(now == t) return lim;
    int res = 0;
    for(int i = head[now]; i && lim > 0; i = e[i].pre){
        cur[now] = i;
        if(i == ban || (i ^ 1) == ban) continue;
        if(dep[e[i].to] != dep[now] + 1 || e[i].flow == 0 || dis[e[i].to] != dis[now] + e[i].cost) continue;
        int incf = dfs(e[i].to, min(lim, e[i].flow));
        if(incf == 0) dep[e[i].to] = 0;
        e[i].flow -= incf; e[i ^ 1].flow += incf;
        res += incf; cst += incf * e[i].cost; lim -= incf;
    }
    return res;
}
int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            int x; scanf("%d",&x);
            add_edge(i, n + j, 1, -x);
        }
    }
    s = n * 2 + 1; t = s + 1;
    for(int i = 1; i <= n; i++) add_edge(s, i, 1, 0);
    for(int i = 1; i <= n; i++) add_edge(n + i, t, 1, 0);
    memcpy(et, e, sizeof(e));
    int final_f = 0, final_c = 0;
    while(SPFA()){
        memcpy(cur, head, sizeof(cur));
        final_f += dfs(s, INF);
    }
    final_c = cst;
    printf("%d\n",-final_c);
    for(int i = 2; i <= cnt; i += 2){
        if(e[i].to == s || e[i].to == t) continue;
        if(e[i ^ 1].to == s || e[i ^ 1].to == t) continue;
        ban = i; cst = 0;
        int flow = 0;
        memcpy(e, et, sizeof(et));
        while(SPFA()){
            memcpy(cur, head, sizeof(cur));
            flow += dfs(s, INF);
        }
        if(cst != final_c) res.push_back(make_pair(e[i ^ 1].to, e[i].to - n));
    }
    sort(res.begin(), res.end());
    for(int i = 0; i < res.size(); i++) printf("%d %d\n",res[i].first,res[i].second);
    return 0;
}
2024/10/11 11:24
加载中...