2019-航电多校第一场

前语-不得不说这是一场爆零的比赛,心疼我自己,比赛时自己傻了,不然应该能做两道简单一点的。

从我做题的顺序开始讲起

 

1005——Path

题意:给你一堆点和单向边(记住是单向!!!要不然我早就过了,不用wa3小时debug),让你删除最小的边,让它不能从1到n走最短路。

一句话题解:就是把所有的最多路搜出来,求最小割

这题我思路来的很快,因为大家知道在跑dij的时候,不重复访问的情况下生成的是一颗最短路径树,难点就在于你如何把所有的最短路同时跑出来,所以在跑dij的时候可以重复的访问一个点(但是从这个点延伸边只有一次,即可以由多个点到达这个点,但是从这个点多次延伸边是重复的没有必要),在访问这个点的时候,把如何访问到这个点记录一下,如果访问到这个点是第一次或者是重复访问,但是距离也是最小值,就把访问这个点的边压到Dinic内,最后用得到的图跑一下最大流即可。

#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e4+10;
typedef long long ll;
typedef pair P;
typedef pair PP;
vector

G1[maxn],G2[maxn]; priority_queue,greater > q; ll used[maxn]; ll d_min[maxn]; ll n,m; struct E { ll u, v, flow; E(ll u = 0, ll v = 0, ll flow = 0): u(u), v(v), flow(flow) {} } edg[maxn*10]; ll cnt_edg, S, T; vector edge[maxn]; // 边集 ll dis[maxn];//距源点距离,分层图 ll current[maxn];//当前弧 void addedg(ll u, ll v, ll flow) { edge[u].push_back(cnt_edg); edg[cnt_edg++] = E(u, v, flow); // 正向边 edge[v].push_back(cnt_edg); edg[cnt_edg++] = E(v, u, 0); // 反向边容量为0 // 正向边下标通过异或就得到反向边下标, 2 ^ 1 == 3 ; 3 ^ 1 == 2 } bool bfs() { queue q; q.push(S); memset(dis, -1, sizeof(dis)); dis[S] = 0; while (!q.empty()) { ll index = q.front(); q.pop(); ll sz = ll(edge[index].size()); for (ll i = 0; i < sz; i++) { E &e = edg[edge[index][i]]; if (e.flow > 0) { if (dis[e.v] < 0) { dis[e.v] = dis[index] + 1; q.push(e.v); } } } } return bool(~dis[T]); // 返回是否能够到达汇点 } ll dfs(ll index, ll maxflow) { if (index == T) return maxflow; // i = current[index] 当前弧优化 ll sz = ll(edge[index].size()); for (ll i = current[index], number; number = edge[index][i], i < sz; i++) { current[index] = i; E &e = edg[number]; if (dis[e.v] == dis[index] + 1 && e.flow > 0) { ll flow = dfs(e.v, min(maxflow, e.flow)); if (flow != 0) { e.flow -= flow; // 正向边流量降低 edg[number ^ 1].flow += flow; // 反向边流量增加 return flow; } } } return 0; // 找不到增广路 退出 } ll dinic() { ll ans = 0; while (bfs()) {// 建立分层图 ll flow; memset(current, 0, sizeof(current)); // BFS后应当清空当前弧数组 ll INF=1e17; while (bool(flow = dfs(S, INF))) // 一次BFS可以进行多次增广 ans += flow; } return ans; } int main() { ll TT; cin>>TT; while(TT--) { cnt_edg=0; for(ll i=0;i>n>>m; S=1; T=n; for(ll i=0;i>x>>y>>z; G1[x].push_back(make_pair(y, z)); } // d v u e q.push(make_pair(make_pair(0, 1), make_pair(0, 0))); while(!q.empty()) { PP t=q.top(); ll d=t.first.first,v=t.first.second,u=t.second.first,e=t.second.second; q.pop(); if(used[v]==1) { if(d==d_min[v]){ addedg(u, v, e); } continue; } addedg(u, v, e); used[v]=1; d_min[v]=d; for(ll i=0;i

 

 

1004——Vacation

题意:给你一堆车排成一条直线,不能超车,每个车都有长度,求最后一辆车的车头到达终点的最短时间

一句话题解:二分答案,前缀和优化

你在计算的时候可以发现,最后一辆车出去时,其他的车都有一个最小距离就行了,不用开特别远,即所有车连在一起时,最后一辆车到达终点,所以一个时间t能否合理,要看是否所有的车都能跑到这个最小距离就行了。(因为第i辆车到达了最小距离,第i+1辆车一定不会因为速度被堵上而到达不了,因为最后这两辆车时脸上的)

T了一发,换了scanf才过,果然cin有点慢啊QAQ

 

#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
ll l[maxn],s[maxn],v[maxn],pre_l[maxn];
int n;
bool J(double tt)
{
    for(int i=0;i<=n;i++)
        if(tt*v[i]1e-7)
        {
            double mid=(r+l)/2;
            if(J(mid))
                r=mid;
            else
                l=mid;
        }
        printf("%.10lf\n",r);
    }
    
}

 

 

待更新(你们的评论就是我更新的动力QAQ,退役前我要拼最后一次!!!)

你可能感兴趣的:(acm)