The First Event of Hangzhou Electricity and Television Multicultural School in 2019

Keywords: network

Only two questions were written on the court: D.E.

D: Vacation (simulation)

Problem Description:
Tom and Jerry are going on a vacation. They are now driving on a one-way road and several cars are in front of them. To be more specific, there are n cars in front of them. The ith car has a length of li, the head of it is si from the stop-line, and its maximum velocity is vi. The car Tom and Jerry are driving is l0 in length, and s0 from the stop-line, with a maximum velocity of v0.
The traffic light has a very long cycle. You can assume that it is always green light. However, since the road is too narrow, no car can get ahead of other cars. Even if your speed can be greater than the car in front of you, you still can only drive at the same speed as the anterior car. But when not affected by the car ahead, the driver will drive at the maximum speed. You can assume that every driver here is very good at driving, so that the distance of adjacent cars can be kept to be 0.
Though Tom and Jerry know that they can pass the stop-line during green light, they still want to know the minimum time they need to pass the stop-line. We say a car passes the stop-line once the head of the car passes it.
Please notice that even after a car passes the stop-line, it still runs on the road, and cannot be overtaken.
(n <= 1e5, l,v,s <= 1e9)

Topic:

n cars on a line, give you their distance from the terminal, maximum speed and length, each car can not overtake, please ask the shortest time for the last car to reach the terminal.

Solutions:

A fast car catching up with a slow one is equivalent to a merger of the two cars.
There is a moment for every two cars to merge. Priority queues can be used to maintain the merger time of each two adjacent vehicles, in the process of maintaining the distance of the last vehicle.
The merger of cars can be achieved by a linked list. Priority queue maintenance should also be added to the merged vehicles and adjacent vehicles at the merging time.
Take out the time to determine whether the car in front of the current car is the original one, if not, then abandon the time, because the car in front has merged with the car.
It is equivalent to simulating the whole process.

ac code:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 50;
struct node{
    double t;//time
    int id;
    int pos;
    node(){};
    node(double a, int b, int c){t = a; id = b;pos = c;}
    bool operator < (const node& x)const{return t > x.t;}
};
int pre[maxn],  nxt[maxn];
double s[maxn], v[maxn], l[maxn];
priority_queue<node> q;
int n;
int head, tail;
double cur = 0.0;//current time
double res = 0.0;//v0 travels
double eps = 1e-10;
double cul(int x){
    int y = nxt[x];
    double d = s[x] - s[y] - l[y] - cur*(v[x] - v[y]);
    //cout<<"sx:"<<s[x]<<" sy:"<<s[y]<<" ly:"<<l[y]<<endl;
    return d/(v[x] - v[y]);
}//It takes more time for the car labeled x to catch up with the car in front of it.
void del(int x){//Merge x and its next car
    int L = pre[x];
    int R = nxt[x];
    nxt[L] = R;
    pre[R] = L;
    l[R] += l[x];
    if(L == head || R == tail) return;
    if(v[R] - v[L] > -eps) return;
    q.push( node(cul(L) + cur, L, R) );
    return;
}
int main()
{
    while(scanf("%d", &n)!=EOF){
        for(int i = 0; i <= n; ++i) scanf("%lf", &l[i]); s[n+1] = 0;
        for(int i = 0; i <= n; ++i) scanf("%lf", &s[i]); v[n+1] = 1e11;
        for(int i = 0; i <= n; ++i) scanf("%lf", &v[i]); l[n+1] = 0;
        int ok = 0;
        cur = res = 0.0;
        for(int i = 1; i <= n; ++i){//Is there any speed smaller than that?
            if(v[0] > v[i]) ok = 1;
        }
        if(!ok){
            double ans = s[0]/v[0];
            printf("%.10f\n", ans);
            continue;
        }
        while(q.size()) q.pop();
        //q.push(node(1e9, n+1,n+1));
        head = maxn-1;
        nxt[head] = 0;
        tail = n+1;
        nxt[tail] = tail;
        pre[tail] = n;

        for(int i = 0; i <= n; ++i){
            pre[i] = i-1;
            if(i == 0) pre[i] = head;
            nxt[i] = i+1;
            if(i == n) break;
            if(v[i+1] - v[i] > -eps) continue;
            q.push(node(cul(i), i, i + 1) );
        }
        double ans;
        int flag = 0;
        while(q.size()){
            node temp = q.top();q.pop();
            int id = temp.id;
            double t = temp.t;
            if(nxt[id] != temp.pos) continue;

            int id0 = nxt[head];
            double v0 = v[id0];
            //cout<<"time: "<<t<<"  road: "<<res + v0*(t-cur)<<endl;
            if(res + v0*(t-cur) >= s[0]){//v0 comes to an end before the next merger
                ans = cur + (s[0] - res)/v0;
                printf("%.10f\n",ans);
                flag = 1;
                break;
            }

            res += v0*(t-cur);
            cur = t;
            del(id);
        }
        if(!flag) {
            double v0 = v[nxt[head]];
            ans = cur + (s[0] - res)/v0;
            printf("%.10f\n", ans);
        }
    }
}
/*
1
1 1
10 0
20 1
1
1 0
10 0
20 1
*/

E: Path (Shortest Path + Network Flow)

Problem Description:
Years later, Jerry fell in love with a girl, and he often walks for a long time to pay visits to her. But, because he spends too much time with his girlfriend, Tom feels neglected and wants to prevent him from visiting her.
After doing some research on the neighbourhood, Tom found that the neighbourhood consists of exactly n houses, and some of them are connected with directed road. To visit his girlfriend, Jerry needs to start from his house indexed 1 and go along the shortest path to hers, indexed n.
Now Tom wants to block some of the roads so that Jerry has to walk longer to reach his girl's home, and he found that the cost of blocking a road equals to its length. Now he wants to know the minimum total cost to make Jerry walk longer.
Note, if Jerry can't reach his girl's house in the very beginning, the answer is obviously zero. And you don't need to guarantee that there still exists a way from Jerry's house to his girl's after blocking some edges.

Topic:

Given a digraph, each edge has its weight. The cost of deleting one edge is its weight. The minimum cost of shortest path lengthening from node 1 to node n is obtained.

Solutions:

The shortest distances of dis1 and dis n from each point to 1 and N are calculated once from node 1 and node n respectively. Considering the weight value of an edge is w, from u to v, if dis1 [u] + W = disn [v], this edge is the shortest one. Find out all the edges on the shortest path, and build a map to find the smallest cut.

#include<iostream>
#include<cstdio>
#include<string.h>
#include<queue>
#define ll long long
using namespace std;
const int maxn = 1e4 +50;
const ll inf = 0x3f3f3f3f3f3f3f3f;
struct node{
	int u,v,nxt;
	ll f;
}e[maxn*10];
int cnt = 0;
int head[maxn];
void add(int u,int v,ll f){
	e[cnt].u = u;
	e[cnt].v = v;
	e[cnt].f = f;
	e[cnt].nxt = head[u];
	head[u] = cnt++;

	e[cnt].u = v;
	e[cnt].v = u;
	e[cnt].f = 0;
	e[cnt].nxt = head[v];
	head[v] = cnt++;
}
int st,ed,ex;
int n, m;
#define P pair<ll, int>
vector<P> g1[maxn], g2[maxn];
ll dis1[maxn], disn[maxn];
priority_queue<P, vector<P>, greater<P> > Q;
void dij1(int S, ll *dis){
    for(int i = 0; i <= n; ++i) dis[i] = inf;
    dis[S] = 0;
    while(Q.size()) Q.pop();
    Q.push(P(dis[S], S));
    while(Q.size()){
        P temp = Q.top();Q.pop();
        int u = temp.second;
        if(dis[u] < temp.first) continue;
        for(int i = 0; i < g1[u].size(); ++i){
            int v = g1[u][i].second;
            ll w = g1[u][i].first;
            if(dis[u] + w < dis[v]){
                dis[v] = dis[u] + w;
                Q.push(P(dis[v], v));
            }
        }
    }
}
void dij2(int S, ll *dis){
    for(int i = 0; i <= n; ++i) dis[i] = inf;
    dis[S] = 0;
    while(Q.size()) Q.pop();
    Q.push(P(dis[S], S));
    while(Q.size()){
        P temp = Q.top();Q.pop();
        int u = temp.second;
        if(dis[u] < temp.first) continue;
        for(int i = 0; i < g2[u].size(); ++i){
            int v = g2[u][i].second;
            ll w = g2[u][i].first;
            if(dis[u] + w < dis[v]){
                dis[v] = dis[u] + w;
                Q.push(P(dis[v], v));
            }
        }
    }
}
void init(){
    scanf("%d%d", &n, &m);
	cnt = 0;
	memset(head, -1, sizeof head);
	for(int i = 1; i <= n; ++i) g1[i].clear(), g2[i].clear();
	while(m--){
        int u, v;
        ll w;
        scanf("%d%d%lld", &u, &v, &w);
        g1[u].push_back(P(w, v));
        g2[v].push_back(P(w, u));
	}
}
int dep[maxn];
int q[maxn*2];
int tot,tail;
bool bfs(){
	memset(dep,-1,(ex+1)<<2);
	dep[st] = 1;
	q[tot = 0] = st,tail = 1;
	while(tot < tail){
		int u = q[tot++];
		if(u == ed) break;
		for(int i = head[u];~i;i = e[i].nxt){
			int v = e[i].v;
			if(dep[v]!=-1 || !e[i].f) continue;
			dep[v] = dep[u] + 1;
			q[tail++] = v;
		}
	}
	return dep[ed]!=-1;
}
int cur[maxn];
ll dfs(int u,ll flow){
	ll res = flow;
	if(u == ed) return flow;
	for(int &i = cur[u];~i;i = e[i].nxt){
		int v = e[i].v;
		if(dep[v]!=dep[u] + 1 || !e[i].f) continue;
		ll d = dfs(v,min(res,e[i].f));
		e[i].f -= d;
		e[i^1].f += d;
		res -= d;
		if(res == 0) break;
	}
	if(flow == res) dep[u] = -1;//Preventing re-search
	return flow - res;
}
ll dinic(){
	ll ans = 0;
	ll d;
	while(bfs()){
		for(int i = 0;i <= ex;++i) cur[i] = head[i];
		while(d = dfs(st,inf)) ans += d;
	}
	return ans;
}
void sol(){
    dij1(1, dis1);
	dij2(n, disn);
	if(dis1[n] == inf){
        cout<<0<<endl;return;
	}
    for(int u = 1; u <= n; ++u){
        for(int i = 0; i < g1[u].size(); ++i){
            int v = g1[u][i].second;
            ll w = g1[u][i].first;
            if(dis1[u] + disn[v] + w == dis1[n]){
                add(u, v, w);
            }
        }
	}
	st = 1; ed = n; ex = n+1;
	printf("%lld\n",dinic());
}
int main(){
    int T;
    cin>>T;
	while(T--){
		init();sol();
	}
}

Posted by HK2ALL on Mon, 22 Jul 2019 02:40:48 -0700