zoukankan      html  css  js  c++  java
  • JZOJ5959【NOIP2018模拟11.8A组】铁路运输

    Description





    Input

    Output

    Data Constraint

    题意:给出一个边权为1的无向图,q次操作,将一条边的边权变为2,每次操作后询问有多少个点的通往1的最短路比所有操作前的最短路小。 

    无向图上的边权修改问题不好做,我们可以考虑将其转换为最短路图。假设我们构建出了一个最短路图,如果我们将这个图中的边变为2,有一个显然的结论这条边一定不能再走了,实际上就是一个删边的操作。进一步地思考,如果有一个时刻一个点可以通往1,那么最短路不变,反之最短路就改变了,所以我们实际上要求出的是每一个点在什么时刻与1断开。 

    对于最短路图,这是一个有向无环图,考虑DP,设f[i]表示i节点断开的时间,将每一条边赋为其断开的时间,那么i节点断开的时间就是它通往1号节点的所有路径上的最小时间的最大值。 

    我们从1号节点往下转移即可。 

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define maxn 100010
    #define maxm 400020
    #define maxd 200020
    using namespace std;
    
    int n,m,q,i,j,k,x,y;
    int em,e[maxm],ec[maxm],nx[maxm],ls[maxn],num[maxm][2];
    int dis[maxn],d[maxd],vis[maxn],ans[maxm];
    int Em,E[maxm],Ec[maxm],Nx[maxm],Ls[maxn],f[maxn];
    
    void spfa(){
    	int t=0,w=1,i,j,x,y;
    	for(i=1;i<=n;i++) dis[i]=1e9,vis[i]=0;
    	vis[1]=1,dis[1]=0;f[1]=q+1;
    	d[1]=1;
    	while (t<w){
    		t=(t+1)%maxd,x=d[t]; vis[x]=0;
    		for(i=ls[x];i;i=nx[i]) if (dis[x]+1<dis[e[i]]){
    			dis[e[i]]=dis[x]+1;
    			if (!vis[e[i]]){
    				vis[e[i]]=1;
    				w=(w+1)%maxd,d[w]=e[i];
    			}
    		}
    	}
    }
    void bfs(){
    	int t=0,w=1,i,j,x,y;
    	for(i=1;i<=n;i++) vis[i]=0;
    	d[1]=1; vis[1]=1;
    	while (t<w){
    		x=d[++t],vis[x]=1;
    		for(i=Ls[x];i;i=Nx[i]) {
    			y=E[i];
    			f[y]=max(f[y],min(f[x],Ec[i]));
    			if (!vis[y]) d[++w]=y,vis[y]=1;
    		}
    	}
    }
    int main(){
    	freopen("train.in","r",stdin);
    	freopen("train.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&q);
    	for(i=1;i<=m;i++){
    		scanf("%d%d",&x,&y);
    		em++; e[em]=y; nx[em]=ls[x]; ls[x]=em; num[i][0]=em; ec[em]=q+1;
    		em++; e[em]=x; nx[em]=ls[y]; ls[y]=em; num[i][1]=em; ec[em]=q+1;
    	}
    	for(i=1;i<=q;i++){
    		scanf("%d",&k);
    		ec[num[k][0]]=ec[num[k][1]]=i;
    	}
    	spfa();
    	for(x=1;x<=n;x++){
    		for(i=ls[x];i;i=nx[i]) 
    		if (dis[x]+1==dis[e[i]])
    			Em++,E[Em]=e[i],Nx[Em]=Ls[x],Ls[x]=Em,Ec[Em]=ec[i];
    	}
    	bfs();	
    	for(i=1;i<=n;i++) ans[f[i]]++;
    	for(i=1;i<=q;i++) ans[i]=ans[i-1]+ans[i];
    	for(i=1;i<=q;i++) printf("%d
    ",ans[i]);
    }
  • 相关阅读:
    怎么导出SQL所有用户表的字段信息
    全面掌握C#中的拖放操作
    C#中使用Hook(钩子)
    如何在winform程序中显示网页
    设置socket.Receive()的等待时延
    局域网QQ(C#版)
    C#实现系统热键的功能
    使用C#在应用程序间发送消息
    某某人整理的c#.net函数列表
    C#串口通信编程类(修改版)
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700969.html
Copyright © 2011-2022 走看看