题号 | A | B | C | D | E | F | G | H | I | J | K | L | M |
状态 | . | . | . | Ο | Ο | . | . | . | . | . | . | . | . |
题意:给出n辆车距离终点的距离,车长,速度。当车撞上前面的车后,速度会和前面这辆车保持一致,求最后一辆车的车头经过终点所需要的时间。
思路:一个显然的结论,如果一辆车会撞上前面的车,那么最后经过终点的时间只和前面这辆车的速度有关,和本身的速度无关。所以我们用双指针,pos1代表当前车,pos2代表我要追赶的车,计算一下是否会在前面的车停下前碰到前面的车(我们假设最后一辆车的车头碰到终点时所有车辆瞬间停止),如果可以的话,那么pos1=pos2,pos2去找下一辆,如果不可以的话,pos2去找下一辆(当前的车不一定只会被前面的车影响)最终扫完找到的车就是最终状态的车速,简单计算可得答案。
#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=100010; struct node{ double len,dis,v; }a[maxn]; int n; double sum[maxn]; bool check(int pos1,int pos2){ double t2=(a[pos2].dis+sum[pos2]-sum[1])/a[pos2].v; double t1=(a[pos1].dis+sum[pos1]-sum[1])/a[pos1].v; if(t1>t2)return false; return true; } int main(){ while(cin>>n){ n++; for(int i=1;i<=n;i++){ scanf("%lf",&a[i].len); sum[i]=sum[i-1]+a[i].len; } for(int i=1;i<=n;i++){ scanf("%lf",&a[i].dis); } for(int i=1;i<=n;i++){ scanf("%lf",&a[i].v); } int pos1=1,pos2=2,car=1; while(pos2<=n){ if(check(pos1,pos2)){ // printf("pos1:%d pos2:%d\n",pos1,pos2); car=pos2; pos1=pos2,pos2++; }else{ pos2++; } } // printf("car:%d\n",car); printf("%.10f\n",(a[car].dis+sum[car]-sum[1])/a[car].v); } }
1005 Path
题意:给出有向图,求阻塞若干条边,使得最短路变长或者阻塞,代价为阻塞的边长和,要求代价最小。
思路:先跑出所有的最短路,把属于最短路的边重新建图,原问题等价于求最小割。
这个想法很简单,但一万个点我不敢写,赛后想一下,感觉最短路的边可能很多,但一定不会是复杂度(即不会有很多拐弯的环),这样找网络流的增广路径的次数不会太多,所以不会超时(强行解释)
#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=10010; ll inf=0x3f3f3f3f3f3f3f3f; struct node { int u; ll w; friend bool operator<(const node &a,const node &b) { return a.w>b.w; } }; priority_queue<node >q; ll dis[2][maxn]; int n,m,u,v,tot[2],head[2][maxn]; ll w; struct edge { int to,Next; ll w; } a[2][maxn<<1]; struct ed{ int u,v; ll w; }in[maxn]; void init() { tot[0]=tot[1]=0; for(int i=1; i<=n; i++) { dis[0][i]=dis[1][i]=inf; head[0][i]=head[1][i]=-1; } } void addv(int u,int v,ll w,int typ) { a[typ][++tot[typ]].to=v; a[typ][tot[typ]].w=w; a[typ][tot[typ]].Next=head[typ][u]; head[typ][u]=tot[typ]; } void dij(int s,int t,int typ){ dis[typ][s]=0; priority_queue<node >q; q.push({s,0}); while(!q.empty()){ node st=q.top(); q.pop(); int u=st.u; for(int i=head[typ][u];i!=-1;i=a[typ][i].Next){ int v=a[typ][i].to; if(dis[typ][v]>dis[typ][u]+a[typ][i].w){ dis[typ][v]=dis[typ][u]+a[typ][i].w; q.push({v,dis[typ][v]}); } } } } struct Edge { int to; ll flow; int nxt; Edge() {} Edge(int to, int nxt, ll flow):to(to),nxt(nxt), flow(flow) {} } edge[maxn << 2]; int hd[maxn], dep[maxn]; int S, T; int N, tol; void Init(int n) { N = n; for (int i = 0; i <=N; ++i) hd[i] = -1; tol = 0; } void add(int u, int v, ll w, ll rw = 0) { edge[tol] = Edge(v, hd[u], w); hd[u] = tol++; edge[tol] = Edge(u, hd[v], rw); hd[v] = tol++; } bool BFS() { for (int i = 0; i <= N; ++i) dep[i] = -1; queue<int>q; q.push(S); dep[S] = 1; while (!q.empty()) { int u = q.front(); q.pop(); for (int i = hd[u]; ~i; i = edge[i].nxt) { if (edge[i].flow && dep[edge[i].to] == -1) { dep[edge[i].to] = dep[u] + 1; q.push(edge[i].to); } } } return dep[T] < 0 ? 0 : 1; } ll DFS(int u, ll f) { if (u == T || f == 0) return f; ll w, used = 0; for (int i = hd[u]; ~i; i = edge[i].nxt) { if (edge[i].flow && dep[edge[i].to] == dep[u] + 1) { w = DFS(edge[i].to, min(f - used, edge[i].flow)); edge[i].flow -= w; edge[i ^ 1].flow += w; used += w; if (used == f) return f; } } if (!used) dep[u] = -1; return used; } ll Dicnic() { ll ans = 0; while (BFS()) { ans += DFS(S, inf); } return ans; } int main(){ int TT; cin>>TT; while(TT--){ cin>>n>>m; init(); for(int i=1;i<=m;i++){ scanf("%d%d%lld",&in[i].u,&in[i].v,&in[i].w); addv(in[i].u,in[i].v,in[i].w,0); addv(in[i].v,in[i].u,in[i].w,1); } dij(1,n,0); dij(n,1,1); tot[0]=0; for(int i=1; i<=n; i++) { head[0][i]=-1; } S=1,T=n; Init(n); for(int i=1;i<=m;i++){ int u=in[i].u,v=in[i].v; ll w=in[i].w; if(dis[0][u]+w+dis[1][v]==dis[0][n]){ add(u,v,w); } } printf("%lld\n",Dicnic()); // printf("debug\n"); } }