uva10160 Servicing Stations

The input consists of more than one description of town (but totally, less than ten descriptions). Every
description starts with number N of towns and number M of pairs of towns directly connected each other. The integers N and M are separated by a space. Every one of the next M rows contains a pair of connected towns, one pair per row. The pair consists of two integers for town's numbers, separated by a space. The input ends with N = 0 and M = 0.
Output
For every town in the input write a line containing the obtained minimum.
Sample Input
8 12
1 2
1 6
1 8
2 3
2 6
3 4
3 5
4 5
4 7
5 6
6 7
6 8
0 0
SampleOutput
      2
  1. 题目大意:给定n个城市,m条无向边分别连接两个城市。若城市x建造了发电厂,则与x相连的城市都有电供应。求使所有城市都有电供应所需的最小发电厂数。
  2. 思路:回溯法+剪枝
  • 可行性剪枝1:若当前已有n个城市有了电,即所有城市都通了电,则记录当前最小值。
  • 可行性剪枝2:若当前搜索到的城市n前面1~n-1编号的城市中有没有通电的,则永远也无法输送电力给那个城市,无解。
  • 剪枝2实现方法:用邻接数组存储每个点相邻的点,将每个邻接数组的点以其编号为关键字降序排序,dfs判断时若前面1~n-1个点中有没有电的,并且它的最大编号儿子的编号小于当前城市(即搜索序更小,已经搜索过却无电),则剪枝。
  • 最优化剪枝:若当前要用的最小发电厂数已经超过了当前求得最有解,则剪枝。
//顺便注意以下:uva上输入时的“while(scanf("%d%d",&n,&m)&&n&&m)“无法通过,要用”while(scanf("%d%d",&n,&m),n+m)”哦;

Accepted 660ms (resourse:virtual judge)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int g[40][40],son[40],n,m,ans;
bool elt[40];
bool cmp(const int &a,const int &b)
{
    return a>b;
}
void Init()
{
    ans=n+1;
    memset(g,0,sizeof(g));
    memset(elt,0,sizeof(elt));
    memset(son,0,sizeof(son));
    for(int i=0; i<m; i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        g[u][son[u]++]=v;
        g[v][son[v]++]=u;
    }
    for(int i=1; i<=n; i++)
    {
        g[i][son[i]++]=i;
        sort(g[i],g[i]+son[i],cmp);
    }
}
void dfs(int cur,int elcity,int sum)
{
    if(sum>=ans)return;//tree cut 1;
    if(elcity==n)
        ans=sum;
    for(int i=1; i<cur; i++) //tree cut 2;
        if((!elt[i])&&(g[i][0]<cur))
            return;
    dfs(cur+1,elcity,sum);
    int k=0,vis[40];
    for(int i=0; i<son[cur]; i++)
        if(!elt[g[cur][i]])
        {
            elt[g[cur][i]]=1;
            vis[k++]=g[cur][i];
        }
    if(!k)return;//tree cut 3;
    dfs(cur+1,elcity+k,sum+1);
    for(int i=0; i<k; i++)
        elt[vis[i]]=0;
}
int main()
{
    while(scanf("%d%d",&n,&m),n+m)
    {
        Init();
        dfs(1,0,0);
        printf("%d\n",ans);
    }
    return 0;
}


 

posted @ 2016-08-10 11:36  keshuqi  阅读(198)  评论(0编辑  收藏  举报