Codeforces Round #364 (Div. 1)

遅いのとA,B逆なことを除けばうまくいった?

A B C D E Place
00:26 00:33 01:28 - - 20th

A:
全然わかりませんでした(オイ
バス乗車時間を二分探索。式もなんだか難しい。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<stdlib.h>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int main(){
	int a,b,c,d,e;
	scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
	double left=0;
	double right=(double)b/d;
	int r=(a+e-1)/e;
	for(int i=0;i<100;i++){
		double M=(left+right)/2;
		double at=0;
		double t=0;
		double x=0;
		for(int j=0;j<r;j++){
			t+=M;
			at+=M*d;
			if(j==r-1)break;
			x=t*c;
			double t2=(at-x)/(c+d);
			x+=t2*c;
			at=x;
			t+=t2;
		}
	//	printf("%f: %f %f\n",M,t,at);
		if(at<b){
			left=M;
		}else right=M;
	}
	//printf("%f\n",left);
	printf("%.12f\n",left+((double)b-left*d)/c);
}

B:
辺ごとに両端の少ない方だけ人が移動する。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<stdlib.h>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int v[210000];
vector<int>g[221000];
long long ret=0;
int sz[221000];
int M;
void dfs(int a,int b){
	for(int i=0;i<g[a].size();i++){
		if(b==g[a][i])continue;
		dfs(g[a][i],a);
		sz[a]+=sz[g[a][i]];
		ret+=min(sz[g[a][i]],M-sz[g[a][i]]);
	}
	if(v[a])sz[a]++;

}
int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	M=b*2;
	for(int i=0;i<b*2;i++){
		int p;scanf("%d",&p);p--;v[p]++;
	}
	for(int i=0;i<a-1;i++){
		int p,q;scanf("%d%d",&p,&q);p--;q--;
		g[p].push_back(q);
		g[q].push_back(p);
	}
	dfs(0,-1);
	printf("%I64d\n",ret);
}

C:
まずDinic (計算量的にも問題なし)。流量0のときと3以上のときは自明。
流量が1,2いずれのときも1つの辺はフローで流れた辺を使う。2のときは残った辺もフローで流れた辺。
フローで使った辺を1つ選び、残りでs->tの移動中必ず通る辺(dfs情報のアレでチェック可能)を全部試せばよい。1のときはフローで使った辺を消したあとBFSしてs->tいけるかどうかも判断する。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<stdlib.h>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
const int D_MAX_V=1002;
const int D_v_size=1002;
struct D_wolf{
	int t,c,r;
	int u,w;
	D_wolf(){t=c=r=u=w=0;}
	D_wolf(int t1,int c1,int r1,int u1,int w1){
		t=t1;c=c1;r=r1;u=u1;w=w1;
	}
};
vector<D_wolf>D_G[D_MAX_V];
int D_level[D_MAX_V];
int D_iter[D_MAX_V];

void add_edge(int from,int to,int cap,int id){
	D_G[from].push_back(D_wolf(to,cap,D_G[to].size(),1,id));
	D_G[to].push_back(D_wolf(from,0,D_G[from].size()-1,0,id));
}
void D_bfs(int s){
	for(int i=0;i<D_v_size;i++)D_level[i]=-1;
	queue<int> Q;
	D_level[s]=0;
	Q.push(s);
	while(Q.size()){
		int v=Q.front();
		Q.pop();
		for(int i=0;i<D_G[v].size();i++){
			if(D_G[v][i].c>0&&D_level[D_G[v][i].t]<0){
				D_level[D_G[v][i].t]=D_level[v]+1;
				Q.push(D_G[v][i].t);
			}
		}
	}
}
int D_dfs(int v,int t,int f){
	if(v==t)return f;
	for(;D_iter[v]<D_G[v].size();D_iter[v]++){
		int i=D_iter[v];
		if(D_G[v][i].c>0&&D_level[v]<D_level[D_G[v][i].t]){
			int d=D_dfs(D_G[v][i].t,t,min(f,D_G[v][i].c));
			if(d>0){
				D_G[v][i].c-=d;
				D_G[D_G[v][i].t][D_G[v][i].r].c+=d;
				return d;
			}
		}
	}
	return 0;
}
int max_flow(int s,int t){
	int flow=0;
	for(;;){
		D_bfs(s);
		if(D_level[t]<0)return flow;
		for(int i=0;i<D_v_size;i++)D_iter[i]=0;
		int f;
		while((f=D_dfs(s,t,99999999))>0){flow+=f;}
	}
	return 0;
}
const int MAXN=1100;
const int MAXM=61000;
int zeit, dis[MAXN], fin[MAXN], low[MAXN], par[MAXN], dep[MAXN];
int kodat[MAXN], koptr[MAXN + 1];
int zu[MAXM];
int ptr[MAXN];
int nxt[MAXM];
int n;
void dfsInfo(int u, int oy, int d) {
	dis[u] = low[u] = zeit++; par[u] = oy; dep[u] = d;
	int i, v;
	for (i = ptr[u]; ~i; i = nxt[i]) if ((v = zu[i]) != oy) {
		if (!~dis[v]) {
			dfsInfo(v, u, d + 1);
			low[u] = min(low[u], low[v]);
		} else {
			low[u] = min(low[u], dis[v]);
		}
	}
	fin[u] = zeit++;
}
void dfsInfos() {
	memset(dis, ~0, n * 4); zeit = 0;
	for (int u = 0; u < n; ++u) if (!~dis[u]) dfsInfo(u, -1, 0);
	for (int u = 0; u < n; ++u) {
		int &j = koptr[u + 1] = koptr[u];
		for (int i = ptr[u]; ~i; i = nxt[i]) if (u == par[zu[i]]) kodat[j++] = zu[i];
	}
}
bool produce(int u, int v) {
	return (dis[u] <= dis[v] && fin[u] >= fin[v]);
}
int related(int u, int v) {
	int s = koptr[u], e = koptr[u + 1], h;
	for (; s + 1 < e; ) {
		h = (s + e) >> 1;
		(dis[kodat[h]] <= dis[v]) ? s = h : e = h;
	}
	return kodat[s];
}
bool isBridge(int u, int v) {
	if (dis[u] > dis[v]) swap(u, v);
	return (u == par[v] && dis[v] <= low[v]);
}
bool isFatalEdge(int u, int v, int a, int b) {
	if (dis[u] > dis[v]) swap(u, v);
	return (u == par[v] && dis[v] <= low[v] && produce(v, a) != produce(v, b));
}
bool isFatalPoint(int u, int a, int b) {
	bool ua = produce(u, a), ub = produce(u, b);
	if (!ua && !ub) {
		return 0;
	} else if (ua && ub) {
		int ra = related(u, a), rb = related(u, b);
		return (ra != rb && (dis[u] <= low[ra] || dis[u] <= low[rb]));
	} else {
		if (ub) swap(a, b);
		return (dis[u] <= low[related(u, a)]);
	}
}
int vis[1100];
int x[31000];
int y[31000];
int z[31000];
int f[1100][1100];
vector<pair<int,int> > G[1100];
int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	int s,t;scanf("%d%d",&s,&t);
	s--;t--;

	for(int i=0;i<b;i++){
		int p,q,r;scanf("%d%d%d",&p,&q,&r);p--;q--;
		f[p][q]++;
		f[q][p]++;
		x[i]=p;y[i]=q;z[i]=r;
		if(p==q)continue;
		add_edge(p,q,1,i);
		add_edge(q,p,1,i);
	}
	int ans=max_flow(s,t);
	if(ans>2){
		printf("-1\n");return 0;
	}
	if(ans==0){
		printf("0\n0\n");return 0;
	}
	for(int i=0;i<a;i++){
		for(int j=0;j<D_G[i].size();j++){
			if(D_G[i][j].u&&D_G[i][j].c==0){
				G[i].push_back(make_pair(D_G[i][j].t,D_G[i][j].w));
			}
		}
	}
	int ret=mod*2;
	int L=-1;
	int R=-1;
	for(int i=0;i<a;i++)for(int j=0;j<G[i].size();j++){
		for(int k=0;k<b;k++){
			zu[k]=nxt[k]=-1;
		}
		for(int k=0;k<=a;k++){
			dis[k]=fin[k]=low[k]=par[k]=dep[k]=kodat[k]=koptr[k]=0;
			ptr[k]=-1;
		}
		int cur=z[G[i][j].second];
		zeit=0;
		int sz=0;
		for(int k=0;k<b;k++){
			if(x[k]==y[k])continue;
			if(G[i][j].second==k)continue;
			zu[sz]=y[k];
			nxt[sz]=ptr[x[k]];
			ptr[x[k]]=sz++;
			zu[sz]=x[k];
			nxt[sz]=ptr[y[k]];
			ptr[y[k]]=sz++;
		}
		n=a;
		if(ans==1&&ret>cur){
			for(int k=0;k<a;k++)vis[k]=0;
			queue<int>Q;
			Q.push(s);
			vis[s]=1;
			while(Q.size()){
				int at=Q.front();Q.pop();
				for(int k=ptr[at];~k;k=nxt[k]){
					if(!vis[zu[k]]){
						vis[zu[k]]=1;
						Q.push(zu[k]);
					}
				}
			}
			if(vis[t]==0){
				ret=cur;
				L=G[i][j].second;
				R=-1;
			}
		}
		dfsInfos();
		for(int k=0;k<b;k++){
			if(x[k]==y[k])continue;
			if(G[i][j].second==k)continue;
			if(ret>cur+z[k]&&isFatalEdge(x[k],y[k],s,t)&&(f[x[k]][y[k]]==1||(f[x[k]][y[k]]==2&&((i==x[k]&&G[i][j].first==y[k])||(i==y[k]&&G[i][j].first==x[k]))))){
				ret=cur+z[k];
				L=G[i][j].second;
				R=k;
			}
		}
	}
	if(~R){
		printf("%d\n2\n%d %d\n",ret,L+1,R+1);
	}else printf("%d\n1\n%d\n",ret,L+1);
}

D:
人間が解ける問題には見えない。Mo+ハフマン木の回転、とかではないなら結構面白いのかも。