ural 1500 Pass Licenses (dfs+bit)

题意:

有n个十字路口(就是路的端点啦)、m条路、k中驾照,每一条路可属于若干种驾照(拥有

相应的驾照才能在这条路上通行)

求从编号为0的十字路口走到编号为1的十字路口,最少要有多少种驾照。


因为驾照数很少,可以用位来模拟相应的驾照。

然后枚举得到既能从0到1又最少的需求。


e[i][j]中为1的位代表这条路属于该驾照。


照着小伙伴的思路自己敲了一遍。。。。感觉结合位运算的搜索真是太神奇了!!!


#include<cstdio>
#include<cstring>
#include<iostream>
#define INF 0x3f3f3f3f
using namespace std;

int k,license[25],n;
int vis[35];
int e[35][35];

void dfs(int s,int now)
{
    vis[s]=1;
    if(s==1) return;
    for(int i=0;i<n;i++)
    {
        if((e[s][i]&now) && !vis[i])
            dfs(i,now);
    }
}

int main()
{
    int m,v1,v2,c,tmp,now,ans,cato,cnt;
    while(scanf("%d%d%d",&k,&n,&m)!=EOF)
    {
        memset(e,0,sizeof(e));
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&v1,&v2,&c);
            e[v1][v2]=(e[v1][v2]|(1<<c));
            e[v2][v1]=e[v1][v2];
        }
        ans=INF;
        int i;
        for(i=0;i<(1<<k);i++)
        {
            tmp=i;
            cnt=0;
            while(tmp)     //剪枝。大于已经求得的
            {               //符合要求所需的驾照数就不必再dfs了
                if(tmp&1)
                    cnt++;
                tmp=tmp>>1;
            }
            if(cnt>=ans) continue;

            memset(vis,0,sizeof(vis));
            now=i;
            dfs(0,now);

            if(vis[1])   //如果能够到1
            {
                ans=0,cato=0;
                while(now)
                {
                    if(now&1)
                    {
                        license[ans++]=cato;
                    }
                    now>>=1;
                    cato++;     //驾照的种类编号
                }
            }
        }
        printf("%d\n",ans);
        for(int i=0;i<ans-1;i++)
            printf("%d ",license[i]);
        printf("%d\n",license[ans-1]);
    }
    return 0;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值