zoukankan      html  css  js  c++  java
  • 《2019 MultiUniversity Training Contest 1》 补

    Path:

    题意:用最少的代价,删除一些边,使得最短路变长。

    思路:

    https://blog.csdn.net/jerry99s/article/details/96907292(大佬讲得非常好)

    我们将所有最短路上的边,建立一张新的图。

    以1为源点,n为汇点。求最小割。

    这时的最小割即为最小花费(这很显然。)

    首先,如何求该条边是最短路上的边。

    在牛客某次比赛时做到过思路。

    对于边(x,y,z),dis表示最短路

    dis[1-x] + z +dis[x-n]。即满足该边是最短路上的边,(这也很显然)。

    那么,先原图跑出1到所有点的最短路。

    然后再建反图,跑出n到所以点的最短路。

    最后枚举边去建图,然后跑最大流即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<LL,int> pii;
    const int N = 1e4+5;
    const int M = 5e4+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    inline int read()
    {
        int 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;
    }
    int n,m,s,t,cnt = -1;
    int head[N],dep[N],cur[N];
    LL dis1[N],dis2[N];
    struct Node{int to;LL dis;int next,st;}e[M<<1],edge[M<<1];
    vector<Node> G[N],RG[N];
    inline void add(int u,int v,int w)
    {
        e[++cnt].to = v,e[cnt].dis = w,e[cnt].next = head[u],head[u] = cnt;
        e[++cnt].to = u,e[cnt].dis = 0,e[cnt].next = head[v],head[v] = cnt;
    }
    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 slove()
    {
        LL ans = 0;
        while(bfs())
        {
            for(int i=1;i<=n;++i) cur[i] = head[i];
            ans += dfs(s,INF);
        }
        return ans;
    }
    void dij(int s,LL *dis,vector<Node> vec[])
    {
        for(int i = 1;i <= n;++i) dis[i] = INF;
        dis[s] = 0;
        priority_queue<pii,vector<pii>,greater<pii> > Q;
        Q.push(pii{dis[s],s});
        while(!Q.empty())
        {
            int u = Q.top().second;
            LL d = Q.top().first;
            Q.pop();
            if(d > dis[u]) continue;
            for(auto v : vec[u])    
            {
                if(dis[v.to] > dis[u]+v.dis)
                {
                    dis[v.to] = dis[u]+v.dis;
                    Q.push(pii{dis[v.to],v.to});
                }
            }
        }
    }
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            n = read(),m = read();
            memset(head,-1,sizeof(head));
            cnt = -1;
            for(int i = 1;i <= n;++i) G[i].clear(),RG[i].clear();
            for(int i = 1;i <= m;++i)
            {
                int x,y,z;
                x = read(),y = read(),z = read();
                edge[i].st = x,edge[i].to = y,edge[i].dis = z;
                G[x].push_back(Node{y,z});
                RG[y].push_back(Node{x,z});
            }
            dij(1,dis1,G);
            dij(n,dis2,RG);
            for(int i = 1;i <= m;++i)
            {
                int x = edge[i].st,y = edge[i].to,z = edge[i].dis;
                if(dis1[x]+dis2[y]+z == dis1[n]) add(x,y,z);
            }
            s = 1,t = n;
            LL ans = slove();
            printf("%lld\n",ans);
        }
        system("pause");
        return 0;
    }
    View Code

    Vacation

    思路1:可二分:二分时间,然后判断这个时间里所有的车能不能都过。(注意不能超车)

    思路2:

    对于0号车的状态:
    无非为两种,始终不会贴前面的车,那么为s0/v0.
    会贴着前面的车,那么这时的最大时间为(L0+s1)/v1。
    同时前面的车又会贴着前面的车,那么为(L1+s2)/v2。
    答案即为其中的最大值。
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<LL,int> pii;
    const int N = 1e5+5;
    const int M = 5e4+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e18
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    inline int read()
    {
        int 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;
    }
    int L[N],s[N],v[N];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            for(int i = 0;i <= n;++i) L[i] = read();
            for(int i = 0;i <= n;++i) s[i] = read();
            for(int i = 0;i <= n;++i) v[i] = read();
            LL sum = 0;
            double ans = (1.0*s[0])/v[0];
            for(int i = 1;i <= n;++i)
            {
                sum += L[i];
                ans = max(ans,(1.0*(sum+s[i]))/v[i]);
            }
            printf("%.12f\n",ans);
        }
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    常用正则表达式
    C#链接常见数据库的方法
    [转]hibernate分页原理
    2020hdu多校第一场比赛及补题
    2020hdu多校第四场比赛及补题
    2020hdu多校第五场比赛及补题
    2020hdu多校第三场比赛及补题
    2020hdu多校第二场比赛及补题
    第二次vj团队赛补题
    字符串距离问题
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13462985.html
Copyright © 2011-2022 走看看