zoukankan      html  css  js  c++  java
  • [转载] $CF543B$ 题解

    阅读原文

    背景:(Codeforces) (Round) (#302) ((Div. 1)) (B) 题, (Codeforces543B)
    给定一张边权全为 (1) 的图。在保证点 (s_1) 到点 (t_1) 的距离不超过 (l_1) 且点 (s_2) 到点 (t_2) 的距离不超过 (l_2) 的条件下,求最多能删去的边数。如果没有合法方案,输出 (-1)
    这题最关键的就是转化模型。一开始我死都没想到正解就是因为忽略了边权全为 (1)
    设点 (i) 到点 (j) 的最短长度为 (dis[i][j]) 。这时原条件就可以转化成求点 (s_1) 到点 (t_1) 的最短路上和点 (s_2) 到点 (t_2) 的最短路上经过的路径边数之和。
    当然,这其中有 (3) 种情况:
    第一种是点 (s_1) 到点 (t_1) 的最短路和点 (s_2) 到点 (t_2) 的最短路没有重叠部分。这个时候两个最短路值直接相加就行。
    第二种是点 (s_1) 到点 (t_1) 的最短路和点 (s_2) 到点 (t_2) 的最短路在点 (i) 和点 (j) 之间重叠。这个时候可以 (O(n^2)) 枚举重叠点 (i)(j) ,在保证路长限制的情况下更新答案就行,答案是 (dis[s_1][i]+dis[s_2][i]+dis[i][j]+dis[j][t_1]+dis[j][t_2])
    第三种也是点 (s_1) 到点 (t_1) 的最短路和点 (s_2) 到点 (t_2) 的最短路在点 (i) 和点 (j) 之间重叠,但是点 (s_2) 到点 (t_2) 的最短路从点 (i) 走向点 (j) ,而点 (s_1) 到点 (t_1) 的最短路从点 (j) 走向点 (i) 。 这个时候做法同上,答案是 (dis[s_1][j]+dis[s_2][i]+dis[i][j]+dis[i][t_1]+dis[j][t_2])
    至于求任意两点的最短路嘛,做 (n)(bfs) 就行。
    整个过程就是这样,如果还有什么不明白的,评论区见!感谢您的耐心阅读!
    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
    	int ret=0,f=1;
    	char ch=getchar();
    	while(ch>'9'||ch<'0')
    	{
    		if(ch=='-')
    			f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		ret=(ret<<1)+(ret<<3)+ch-'0';
    		ch=getchar();
    	}
    	return ret*f;
    }
    int n,m,x,y,s1,s2,t1,t2,l1,l2,ans;
    int num,head[6005],dis[3005][3005],vis[3005];
    struct edge
    {
    	int ver,nxt;
    }e[6005];
    queue<int> q;
    inline void adde(int u,int v)
    {
    	e[++num].ver=v;
    	e[num].nxt=head[u];
    	head[u]=num;
    }
    inline void bfs(int s)
    {
    	memset(vis,0,sizeof(vis));
    	q.push(s);
    	vis[s]=1;
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		for(register int i=head[x];i;i=e[i].nxt)
    		{
    			int y=e[i].ver;
    			if(vis[y])
    				continue;
    			vis[y]=1;
    			dis[s][y]=dis[s][x]+1;
    			q.push(y);
    		}
    	}
    }
    int main()
    {
    	n=read();
    	m=read();
    	for(register int i=1;i<=m;i++)
    	{
    		x=read();
    		y=read();
    		adde(x,y);
    		adde(y,x);
    	}
    	for(register int i=1;i<=n;i++)
    		bfs(i);
    	s1=read();
    	t1=read();
    	l1=read();
    	s2=read();
    	t2=read();
    	l2=read();
    	if(dis[s1][t1]>l1||dis[s2][t2]>l2)
    	{
    		printf("-1
    ");
    		return 0;
    	}
    	ans=dis[s1][t1]+dis[s2][t2];
    	for(register int i=1;i<=n;i++)
    	{
    		for(register int j=1;j<=n;j++)
    		{
    			if(dis[s1][i]+dis[i][j]+dis[j][t1]<=l1&&dis[s2][i]+dis[i][j]+dis[j][t2]<=l2)
    				ans=min(ans,dis[s1][i]+dis[i][j]+dis[j][t1]+dis[s2][i]+dis[j][t2]);
    			if(dis[s1][j]+dis[i][j]+dis[i][t1]<=l1&&dis[s2][i]+dis[i][j]+dis[j][t2]<=l2)
    				ans=min(ans,dis[s1][j]+dis[i][j]+dis[i][t1]+dis[s2][i]+dis[j][t2]);
    		}
    	}
    	printf("%d
    ",m-ans);
    	return 0;
    }
    
  • 相关阅读:
    从书上学的东西(顺带总结一发)
    网上讲的好的知识点汇总
    土地征用题解(兼斜率优化详解)
    Blocks题解(区间dp)
    高精度模板汇总
    动态规划总结
    异或序列(题解)(莫队)
    小Z的袜子(题解)(莫队)
    小B的询问(题解)(莫队)
    凸包模板——Graham扫描法
  • 原文地址:https://www.cnblogs.com/Peter0701/p/11519439.html
Copyright © 2011-2022 走看看