幻想乡的异变
发布时间: 2017年7月11日 20:01 最后更新: 2017年7月11日 20:48 时间限制: 1000ms 内存限制: 128M
幻想乡有n座神社,从1到n编号。一些神社间有单相的传送阵,花费一定时间可以从一座神社传送到另一座神社传送到另一座神社,但传送阵的法力只够一个人传送,且只能传送一次。现在灵梦等人要赶去n号神社解决异变,她们从1号神社同时出发,各自选择一条耗时最短的路线,然后同时到达n号神社。灵梦想要知道,在这个前提下,最多能派多少人解决异变。
第一行两个整数n,m,代表神社数量和传送阵数量。
接下来m行,每行三个整数i,j,k,描述一个可以从神社i到神社j,耗时为k的单向传送阵。同一对神社间可以有多个传送阵,每个传送阵恰好被描述一次。
一行一个整数,代表在耗时最少的前提下,能派出的人数。
56 1 2 3 2 5 2 1 3 2 3 5 2 1 4 3 4 5 1
2
#include<iostream> #include<cstring> #include<cstdio> #define inf 0x3f3f3f3f using namespace std; const int N = 100005; int last[N],num[405][405],dist[405][405],o[405][405],cnt=1,n,m,h[20005],q[20005],T,S,inq[N],dis[N],u[10005],v[10005],w[10005]; struct Edge{ int to,next,v,id; }e[N*10]; void ins( int u, int v, int w ){ e[++cnt].to = v; e[cnt].next = last[u]; e[cnt].v = w; last[u] = cnt; e[++cnt].to = u; e[cnt].next = last[v]; e[cnt].v = 0; last[v] = cnt; } bool bfs(){ memset(h,-1,sizeof(h)); int tail = 1, head = 0; q[0] = S; h[S] = 0; while( tail != head ){ int now = q[head++]; for( int i = last[now]; i; i = e[i].next ) if( h[e[i].to] == -1 && e[i].v ){ h[e[i].to] = h[now] + 1; q[tail++] = e[i].to; } } return h[T] != -1; } int dfs( int x, int f ){ int w,used=0; if( x == T ) return f; for( int i = last[x]; i; i = e[i].next ) if( h[e[i].to] == h[x] + 1 && e[i].v ){ w = dfs(e[i].to,min(e[i].v,f-used)); e[i].v -= w; e[i^1].v += w; used += w; if( f == used ) return f; } if( !used ) h[x] = -1; return used; } int dinic(){ int res = 0; while( bfs() ){ res += dfs(S,inf); } return res; } int main(){ freopen("change.in","r",stdin); freopen("change.out","w",stdout); memset(dist,0x3f,sizeof(dist)); scanf("%d%d", &n, &m); for( int i = 1; i <= m; i++ ) { int p,q,r; scanf("%d%d%d",&p,&q,&r); if( r < dist[p][q] ) { dist[p][q] = r; num[p][q] = 1; } else if( r == dist[p][q] ) num[p][q]++; } for( int i = 1; i <= n; i++ ) for( int j = 1; j <= n; j++ ){ if(i==j) dist[i][j]=0; o[i][j]=dist[i][j]; } S=1; T=n; for( int k = 1; k <= n; k++ ) for( int i = 1; i <= n; i++ ) for( int j = 1; j <= n; j++ ) if( dist[i][j] > dist[i][k]+dist[k][j] ) dist[i][j] = dist[i][k]+dist[k][j]; if( dist[S][T] == 0x3f3f3f3f ) puts("0"); else{ for( int i = 1; i <= n; i++ ) for( int j = 1; j <= n; j++ ) if( dist[S][i]+o[i][j]+dist[j][T] == dist[S][T] ) for( int k = 1; k <= num[i][j]; k++ ) ins(i,j,1); printf("%d\n",dinic()); } return 0; }
幻想乡的异变
发布时间: 2017年7月11日 20:01 最后更新: 2017年7月11日 20:48 时间限制: 1000ms 内存限制: 128M
幻想乡有n座神社,从1到n编号。一些神社间有单相的传送阵,花费一定时间可以从一座神社传送到另一座神社传送到另一座神社,但传送阵的法力只够一个人传送,且只能传送一次。现在灵梦等人要赶去n号神社解决异变,她们从1号神社同时出发,各自选择一条耗时最短的路线,然后同时到达n号神社。灵梦想要知道,在这个前提下,最多能派多少人解决异变。
第一行两个整数n,m,代表神社数量和传送阵数量。
接下来m行,每行三个整数i,j,k,描述一个可以从神社i到神社j,耗时为k的单向传送阵。同一对神社间可以有多个传送阵,每个传送阵恰好被描述一次。一行一个整数,代表在耗时最少的前提下,能派出的人数。
复制56 1 2 3 2 5 2 1 3 2 3 5 2 1 4 3 4 5 12
//std不想写
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 400010 int nd[maxn],to[maxn],nxt[maxn],flow[maxn],cap[maxn],teg=1; bool ab[maxn]; int S,T; void adeg(int p,int q,int cp) { to[++teg]=q; nxt[teg]=nd[p]; nd[p]=teg; cap[teg]=cp; to[++teg]=p; nxt[teg]=nd[q]; nd[q]=teg; } int stk[maxn],ta,fr,d[maxn]; int cur[maxn]; bool v[maxn]; bool bfs() { for(int i=1; i<=T; i++) v[i]=false; v[S]=true; ta=1,fr=0; stk[++fr]=S; d[S]=0; while(ta<=fr) { int cur=stk[ta++]; for(int i=nd[cur]; i; i=nxt[i]) if(ab[i] && cap[i]>flow[i] && !v[to[i]]) { v[to[i]]=true; d[to[i]]=d[cur]+1; stk[++fr]=to[i]; } } return v[T]; } int dfs(int x,int a) { if(x==T || a==0) return a; int now=0; for(int &i=cur[x]; i; i=nxt[i]) if(ab[i] && d[to[i]]==d[x]+1 && cap[i]>flow[i]) { int f=dfs(to[i],min(a,cap[i]-flow[i])); if(f) { now+=f; flow[i]+=f; flow[i^1]-=f; a-=f; if(!a) break; } } return now; } int dinic() { int ans=0; while(bfs()) { for(int i=1; i<=T; i++) cur[i]=nd[i]; ans+=dfs(S,0x3f3f3f3f); } return ans; } int n,k,cnt1=0,cnt=0; struct cd { int p,t,l; }P1[maxn],oth[maxn]; bool ntpm[20000010]; int pme[2000010],pmecnt=0; int bel_edg[maxn]; int main() { freopen("card.in","r",stdin); freopen("card.out","w",stdout); for(int i=2; i<=20000000; i++) { if(!ntpm[i]) pme[++pmecnt]=i; for(int j=1; j<=pmecnt && 1ll*pme[j]*i<=20000000; j++) { ntpm[i*pme[j]]=true; if(i%pme[j]==0) break; } } scanf("%d%d",&n,&k); //define: "1" at the "last" position! for(int i=1; i<=n; i++) { int p,t,l; scanf("%d%d%d",&p,&t,&l); if(t==1) { cnt1++; P1[cnt1].p=p; P1[cnt1].t=t; P1[cnt1].l=l; } else { cnt++; oth[cnt].p=p; oth[cnt].t=t; oth[cnt].l=l; } } //not considering 1 //left: odd right: even for(int i=1; i<=cnt; i++) if(oth[i].t&1) for(int j=1; j<=cnt; j++) if(!ntpm[oth[i].t+oth[j].t]) //conflict { adeg(i,j,0x3f3f3f3f); ab[teg]=true; ab[teg^1]=true; } //considering 1 if(cnt1) { S=cnt+2,T=S+1; for(int i=1; i<=cnt; i++) if(!ntpm[1+oth[i].t]) { adeg(S-1,i,0x3f3f3f3f); ab[teg]=true; ab[teg^1]=true; } } else S=cnt+1,T=S+1; for(int i=1; i<=cnt; i++) { bel_edg[i]=teg+1; if(oth[i].t&1) adeg(S,i,oth[i].p); else adeg(i,T,oth[i].p); } if(cnt1) { bel_edg[0]=teg+1; //indicating point 1 adeg(S,S-1,0); } //quarting answer int l=1,r=1000000001,mid=(l+r)>>1; while(l<r) { //check: if it is able to build one, with level <= mid? int tot=0; for(int i=1; i<=cnt; i++) if(oth[i].l<=mid) tot+=oth[i].p,ab[bel_edg[i]]=1,ab[bel_edg[i]^1]=1; else ab[bel_edg[i]]=0,ab[bel_edg[i]^1]=0; if(cnt1) { int bt=0; for(int i=1; i<=cnt1; i++) if(P1[i].l<=mid && P1[i].p>bt) bt=P1[i].p; ab[bel_edg[0]]=1,ab[bel_edg[0]^1]=1; cap[bel_edg[0]]=bt; tot+=bt; } memset(flow,0,sizeof(flow)); if(tot-dinic()>=k) r=mid; else l=mid+1; mid=(l+r)>>1; } if(mid==1000000001) puts("-1"); else printf("%d\n",mid); fclose(stdin); fclose(stdout); return 0; }
T3
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #define pa pair<long long,int> using namespace std; typedef long long ll; const int N = 100000 + 5; int scnt,id,n,m,cnt,top,tail; int dfn[N],low[N],last[N],belong[N],inq[N],q[N],v[N],u[N],w[N]; ll d1[N],d2[N]; struct Edge{ int to,next,v; }e[N*4]; void insert( int u, int v, int w ){ e[++cnt].to = v; e[cnt].next = last[u]; e[cnt].v = w; last[u] = cnt; } void tarjan( int x ){ int now = 0; dfn[x] = low[x] = ++id; q[++top] = x; inq[x] = 1; for( int i = last[x]; i; i = e[i].next ) if( !dfn[e[i].to] ){ tarjan(e[i].to); low[x] = min(low[x],low[e[i].to]); } else if( inq[e[i].to] ) low[x] = min(low[x],dfn[e[i].to]); if( low[x] == dfn[x] ){ scnt++; while( now != x ){ now = q[top--]; belong[now] = scnt; inq[now] = 0; } } } struct edg{ ll w1,w2; int t; bool operator <(const edg &oth)const{ return w1>oth.w1 || (w1==oth.w1 && w2>oth.w2); } edg(ll _a=0,ll _b=0,int _c=0) {w1=_a,w2=_b,t=_c;} }; bool vis[N]; priority_queue<edg> Q; void dijkstra(){ for( int i = 1; i <= n; i++ ) d1[i] = d2[i] = 1ll<<60; d1[1] = d2[1] = 0; Q.push(edg(0,0,1)); while( !Q.empty() ){ int now = Q.top().t; Q.pop(); if( vis[now] ) continue; vis[now] = 1; for( int i = last[now]; i; i = e[i].next ){ if( d1[e[i].to] > d1[now] + (belong[now]==belong[e[i].to]) || (d1[e[i].to] == d1[now] + (belong[now]==belong[e[i].to]) && d2[e[i].to] > d2[now]+ e[i].v )){ d1[e[i].to] = d1[now] + (belong[now]==belong[e[i].to]); d2[e[i].to] = d2[now] + e[i].v; Q.push(edg(d1[e[i].to],d2[e[i].to],e[i].to)); } } } } int main(){ freopen("festival.in","r",stdin); freopen("festival.out","w",stdout); scanf("%d%d", &n, &m); for( int i = 1; i <= m; i++ ){ scanf("%d%d%d", &u[i], &v[i], &w[i]); insert(v[i],u[i],w[i]); } for( int i = 1; i <= n; i++ ) if( !dfn[i] ) tarjan(i); dijkstra(); for( int i = 2; i <= n; i++ ) if( d1[i] == 1ll<<60 ) printf("-1\n"); else printf("%I64d %I64d\n", d1[i], d2[i]); return 0; }