UVALIVE 6958 Indoorienteering

题目大意:有不超过14个点组成的完全图,给出邻接矩阵,问是否存在长度为W的欧拉回路?

     数据范围:n<=14, w<=1e15;

     standard input/output 7 s, 256 MB

分析:直接暴力是14!的复杂度,显然不能通过;

   考虑折半搜索,我们取0号点为起点,然后把所有的点分成两半;

   两边分别暴力跑,最后检查一边,看另一边是否有可行的路径即可;

   复杂度为C(N,N/2)*(n/2)!;

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cassert>
#include <ctime>
#define rep(i,m,n) for(i=m;i<=(int)n;i++)
#define inf 0x3f3f3f3f
#define mod 1000000007
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
#define ls (rt<<1)
#define rs (rt<<1|1)
#define all(x) x.begin(),x.end()
const int maxn=1e5+10;
const int N=4e5+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
int n,m,k,t,c[2];
ll w,d[14][14];
set<ll>dp[14];
bool flag;
void dfs(int pos,int sta,ll now,int lim,int tp)
{
    if(flag)return;
    int i;
    sta|=(1<<pos);
    if(lim==0)
    {
        if(tp==1)
        {
            rep(i,1,n-1)
            {
                if(c[tp]>>i&1)continue;
                if(dp[i].find(w-now-d[i][pos])!=dp[i].end())
                {
                    flag=true;
                    return;
                }
            }
        }
        else dp[pos].insert(now);
        return;
    }
    rep(i,0,n-1)
    {
        if((sta>>i&1)||(c[tp]>>i&1)==0)continue;
        dfs(i,sta,now+d[pos][i],lim-1,tp);
    }
}
int main(){
    int i,j;
    scanf("%d%lld",&n,&w);
    rep(i,0,n-1)rep(j,0,n-1)scanf("%lld",&d[i][j]);
    if(n==2)
    {
        if(d[0][1]+d[1][0]==w)puts("possible");
        else puts("impossible");
    }
    else
    {
        int all=((1<<n)-2);
        for(i=all-1;i;i=((i-1)&all))
        {
            if(__builtin_popcount(i)!=n/2)continue;
            c[0]=c[1]=0;
            rep(j,1,n-1)
            {
                if(i>>j&1)c[0]|=(1<<j);
                else c[1]|=(1<<j);
            }
            dfs(0,0,0,n/2,0);
            dfs(0,0,0,n-1-n/2,1);
            rep(j,0,n-1)dp[j].clear();
            if(flag)break;
        }
        puts(flag?"possible":"impossible");
    }
    return 0;
}
posted @ 2017-09-29 19:25  mxzf0213  阅读(295)  评论(0编辑  收藏  举报