• FZU Problem 2169 shadow


    http://acm.fzu.edu.cn/problem.php?pid=2169

    题目大意:

    S王国有N个城市,有N-1条道路。王都为编号1的城市。叛军驻扎在很多城市。除了王都外有K个城市有军队,这K支军队要向王都进军,而且消灭沿途经过的城市中的叛军。每支军队仅仅能沿着道路走,而且是其所在城市与王都之间的最短路线走。问可以消灭多少叛军?


    思路:

    有两种方法。

    注意到题目仅仅有N-1条边。是一颗树。

    我想到的是对编号为1的结点(也就是王都,作为跟结点)进行DFS,一直遍历到树叶为止。沿途若发现有军队的,则往上传递可消灭叛军的信息。详见代码。

    A了之后看了看别人的思路有方法二:

    是对每一个有军队的城市进行SPFA。每次消灭一次叛军就把叛军消除(Num置为0) 直到没有叛军或者所有军队遍历完。

    但我总认为怪怪的,军队向王都经过最短路径,可是方向不一定对啊!

    如以下这组数据:

    11 1
    0 0 0 0 0 3 4 0 5 0 0

    1 2 
    2 3
    2 4
    3 5
    5 6
    5 7
    7 8
    8 9
    8 10
    9 11

    SPFA的结果为12.而DFS的为0.

    按我对题目的理解也是0.

    两个代码均AC。题目含糊。。



    方法一:DFS

    #include<cstdio>
    #include<cstring>
    const int MAXN=100000+10;
    const int INF=0x3ffffff;
    int head[MAXN],len,n,k,ans;
    int num[MAXN];
    bool vis[MAXN], army[MAXN];
    struct edge
    {
    	int to,next;
    }e[MAXN<<1];
    
    void add(int from,int to)
    {
    	e[len].to=to;
    	e[len].next=head[from];
    	head[from]=len++;
    }
    
    bool dfs(int cur)
    {
    	for(int i=head[cur];i!=-1;i=e[i].next)
    	{
    		int id=e[i].to;
    		if(vis[id])
    			continue;
    		vis[id]=true;
    		if(dfs(id))
    		{
    			if(num[id]!=0)
    				ans+=num[id];
    			return true;
    		}
    		if(army[id] ==true)  //有军队
    			return true;		
    	}
    	return false;
    }
    
    int main()
    {
    	while(~scanf("%d%d",&n,&k))
    	{
    		int cnt=0;
    		memset(head,-1,sizeof(head));
    		memset(vis,0,sizeof(vis));
    		len=0;
    
    		for(int i=1;i<=n;i++)	
    		{
    			scanf("%d",&num[i]);
    			if(num[i])
    				cnt++;
    		}
    		
    		for(int i=0;i<k;i++)
    		{
    			int temp;
    			scanf("%d",&temp);
    			army[temp]=true;
    		}
    
    		for(int i=1;i<n;i++)
    		{
    			int from,to;
    			scanf("%d%d",&from,&to);
    			add(from,to);
    			add(to,from);
    		}
    		ans=0;
    		dfs(1);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }


    方法二:SPFA

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int MAXN=100000+10;
    const int INF=0x3ffffff;
    int head[MAXN],len,n,k;
    int num[MAXN], army[MAXN];
    int dis[MAXN];
    bool vis[MAXN];
    struct edge
    {
    	int to,next;
    }e[MAXN<<1];
    
    void add(int from,int to)
    {
    	e[len].to=to;
    	e[len].next=head[from];
    	head[from]=len++;
    }
    
    void spfa(int s)
    {
    	queue<int> q;
    	for(int i=1;i<=n;i++)
    	{
    		dis[i]=INF;
    		vis[i]=false;
    	}
    	q.push(s);
    	dis[s]=0;
    	while(!q.empty())
    	{
    		int cur=q.front();
    		q.pop();
    		vis[cur]=false;
    		for(int i=head[cur];i!=-1;i=e[i].next)
    		{
    			int id=e[i].to;
    			if(dis[id] > dis[cur] + 1)
    			{
    				dis[id]=dis[cur]+1;
    				if(!vis[id])
    				{
    					q.push(id);
    					vis[id]=true;
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	while(~scanf("%d%d",&n,&k))
    	{
    		int cnt=0;
    		memset(head,-1,sizeof(head));
    		len=0;
    
    		for(int i=1;i<=n;i++)	
    		{
    			scanf("%d",&num[i]);
    			if(num[i])
    				cnt++;
    		}
    		
    		for(int i=0;i<k;i++)
    			scanf("%d",&army[i]);
    
    		for(int i=1;i<n;i++)
    		{
    			int from,to;
    			scanf("%d%d",&from,&to);
    			add(from,to);
    			add(to,from);
    		}
    		int ans=0;
    		for(int i=0;i<k;i++)
    		{
    			spfa(army[i]);
    
    			for(int j=1;j<=n;j++)
    			{
    				if(!num[j] || dis[j]==INF) //不能到达或者没有叛军
    					continue;
    				ans+=num[j];
    				num[j]=0;
    				cnt--;
    				if(cnt==0)
    					goto next;
    			}
    		}
    next:
    		printf("%d
    ",ans);
    	}
    	return 0;
    }


  • 相关阅读:
    4、redis之使用commons-pool
    好用的eclipse properties插件
    1、redis之安装与配置
    谷歌浏览器禁止window.close的问题
    在浏览器中使用JS打开并展示PDF文件
    JAVA遍历Map的方法
    GEOS库学习之三:空间关系、DE-9IM和谓词
    GEOS库的学习之二:简单几何图形的创建
    GEOS库的学习之一:介绍和编译
    GEOS库在windows中的编译和测试(vs2012)
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/3907118.html
Copyright © 2020-2023  润新知