《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
原文地址:https://www.cnblogs.com/zwjzwj/p/13462985.html