1500. Pass Licenses 夜

http://acm.timus.ru/problem.aspx?space=1&num=1500

bfs 状态压缩  对应K N M

有 1<<K 个状态代表那种类型的边用 或不用

对每个状态就行bfs求解最短路 若可以搜到或者所求值一定不是最优  则包含这个状态的状态就不用求了 这个剪枝很重要

代码及其注释:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include <iomanip>
using namespace std;
#define LL long long
#define sint short int
const int INF=0x3f3f3f3f;
//priority_queue<int,vector<int>,greater<int> >qt;
const int N=31;
int side[N][N];//两个点之间有哪几种边 用状态压缩表示
bool can[1<<20];//这种状态要不要求
int qu[N];//队列
int ans,K;//最优个数 和状态
bool to[N];//广搜时看能不能到底某个点
int n,m,k;
bool bfs(int w)//返回true 则包含这个状态的状态就不用搜了
{
    int sum=0;
    for(int i=0;i<k;++i)
    if(w&(1<<i))
    ++sum;
    if(sum>=ans)//一定不是最优
    return true;
    memset(to,false,sizeof(to));
    to[0]=true;
    qu[0]=0;
    int L=0,R=1;
    while(L<R)
    {
        int x=qu[L++];
        for(int i=1;i<n;++i)
        {
            if(!to[i]&&(w&side[x][i]))
            {
                if(i==1)
                {ans=sum;K=w;return true;}//更新答案
                to[i]=true;
                qu[R++]=i;
            }
        }
    }
    return false;
}
int main()
{
    //freopen("data.in","r",stdin);
    while(scanf("%d %d %d",&k,&n,&m)!=EOF)
    {
        memset(can,true,sizeof(can));
        memset(side,0,sizeof(side));
        while(m--)
        {
            int l,r,w;
            scanf("%d %d %d",&l,&r,&w);
            side[l][r]=(side[l][r]|(1<<w));//记录两点之间有哪几种边
            side[r][l]=(side[r][l]|(1<<w));
        }
        ans=INF;
        int h=(1<<k)-1;
        for(int i=1;i<=h;++i)
        {
            if(can[i])
            {
                if(bfs(i))
                {
                    for(int l=i;l<=h;l=((l+1)|i))//把包含这个状态的状态标记 不用再求
                    can[l]=false;
                }
            }
        }
        printf("%d\n",ans);
        bool first=true;
        for(int i=0;i<k;++i)
        if(K&(1<<i))
        {
            if(first)
            {printf("%d",i);first=false;}
            else
            printf(" %d",i);
        }
        printf("\n");
    }
}

  

原文地址:https://www.cnblogs.com/liulangye/p/2802043.html