《1625: Secret Milking Machine》

一开始一直想着最短路松弛,但是发现这样很难处理T条长度排序的边。

正解:二分最大限制边,然后最大流去check。

对于边 <= 最大限制边的就可以连接两点,容量为1。

然后最后汇点和源点连1,n,容量为INF。

最后判断最大值是否大于二分值即可。

细节:边数组要开4倍,因为无向图加反向边。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 205;
const int M = 4e4+5;
const LL Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

int n,p,T,tot = -1,head[N],dep[N],cur[N],s,t;
struct Input{int st,to,dis;}mm[M];
struct Node{int to,dis,next;}e[M << 2];
inline void add(int u,int v,int w)
{
    e[++tot].to = v,e[tot].dis = w,e[tot].next = head[u],head[u] = tot;
    e[++tot].to = u,e[tot].dis = 0,e[tot].next = head[v],head[v] = tot;
}
bool bfs()//分层
{
    queue<int> Q;
    memset(dep,-1,sizeof(dep));
    dep[s] = 0;
    Q.push(s);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int y = e[i].to,d = e[i].dis;
            if(dep[y] == -1 && d > 0)
            {
                dep[y] = dep[u]+1;
                Q.push(y);
            }
        }
    }
    return dep[t] != -1;
}
int dfs(int u,int flow)
{
    int nowflow = 0,k;
    if(u == t) return flow;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        cur[u] = i;//当前弧优化
        int y = e[i].to,d = e[i].dis;
        if((dep[y] == dep[u]+1) && d > 0)
        {
            if(k = dfs(y,min(flow-nowflow,d)))
            {
                e[i].dis -= k;
                e[i^1].dis += k;
                nowflow += k;
                if(nowflow == flow) break; 
            }
        }
    }
    if(nowflow == 0) dep[u] = -1;//炸点优化
    return nowflow;
}
LL solve()
{
    LL ans = 0;
    while(bfs())
    {
        for(int i = 1;i <= n;++i) cur[i] = head[i];
        ans += dfs(s,INF);
    }
    return ans;
}
bool check(int x)
{
    tot = -1,s = 0,t = n + 1;
    for(int i = 0;i <= n + 1;++i) head[i] = -1;
    for(int i = 1;i <= p;++i)
    {
        if(mm[i].dis <= x) add(mm[i].st,mm[i].to,1),add(mm[i].to,mm[i].st,1);
    }
    add(s,1,INF),add(n,t,INF);
    LL ans = solve();
    if(ans >= T) return true;
    return false;
}
int main()
{
    n = read(),p = read(),T = read();
    int mx = 0;
    for(int i = 1;i <= p;++i) mm[i].st = read(),mm[i].to = read(),mm[i].dis = read(),mx = max(mx,mm[i].dis);
    int L = 0,r = mx,ans = 0;
    while(L <= r)
    {
        int mid = (L + r) >> 1;
        if(check(mid)) r = mid - 1,ans = mid;
        else L = mid + 1;
    }
    printf("%d\n",ans);
    system("pause");
    return 0;
}
View Code

 

posted @ 2020-12-09 20:04  levill  阅读(74)  评论(0编辑  收藏  举报