Tourist Attractions 【三元环】

时间:2019-11-08
本文章向大家介绍Tourist Attractions 【三元环】,主要包括Tourist Attractions 【三元环】使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本人水平有限,题解不到为处,请多多谅解

本蒟蒻谢谢大家观看

题目:

题目描述

在美丽的比特镇一共有n个景区,编号依次为1到n它们之间通过若干条双向道路连接。 Byteasar 慕名来到了比特镇旅游,不过由于昂贵的门票费,他只能负担起 4 个景区的门票费。他可 以在任意景区开始游览,然后结束在任意景区。 Byteasar 的旅游习惯比较特殊,一旦他路过了一个景区,他就一定会进去参观,并且他永远不会参 观同一个景区两次。所以他想知道,有多少种可行的旅游路线,使得他可以恰好参观 4 个景区呢?即 有多少条简单路径恰好经过了 4 个点。

输入格式

第一行包含两个整数n,表示景区的总数。 第 2 至第 n +1 行,每行一个长度为 n 的 01 字符串,第 i+1 行第 j 个字符为 0 表示 i 和 j 之间 没有道路,为 1 表示有一条道路。 输入数据保证 (i,j) 的连接情况等于 (j,i) 的连接情况,且 (i,i) 恒为 0。

输出格式

输出一行一个整数,即可行的路线总数。

样例输入
4 0101 1010 0101 1010

样例输出
8

本题大意:

找出一个三元环,因为三元环一定不能满足题目意思

本题只需要有一条路径能经过4个不同的点即可(可以为环)

如果不是三元环,我们就用排列组合来求出不是三元环的。

我们可以先全部当成可行方案,最后把三元环的数给减掉即可

三元环用bitset优化

因为统计的ans会爆int,因为我们用排列组合方式求,所以要开long long

具体bitset应用请点:click_here

code:
 1 #include<bits/stdc++.h>
 2 #pragma GCC optimize(3)
 3 const int N=1510;
 4 using namespace std;
 5 char a[N][N];
 6 bitset<N>sum[N],p;
 7 int num[N],tot,n;
 8 long long ans=0;
 9 int ver[N*N],head[N*N],nxt[N*N];
10 void inint(){
11     freopen("tour.in","r",stdin);
12     freopen("tour.out","w",stdout);
13 }
14 inline int read(){
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
17     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
18     return x*f;
19 }
20 inline void write(int x)
21 {
22     if(x<0)x=-x,putchar('-');
23     if(x>9)write(x/10);
24     putchar(x%10+'0');
25 }
26 void add(int x,int y){
27     ++tot;
28     ver[tot]=y;
29     nxt[tot]=head[x];
30     head[x]=tot;
31     num[x]++;//统计度数 
32 }
33 int main()
34 {
35     //inint();
36     n=read();
37     for(int i=1;i<=n;i++){
38         for(int j=1;j<=n;j++){
39             cin>>a[i][j];
40             if(a[i][j]=='1'){
41                 sum[i][j]=1;//有边 
42                 add(i,j);//建单向边 
43             }
44         }
45     } 
46     for(int i=1;i<=n;i++){
47         for(int j=head[i];j;j=nxt[j]){
48             int y=ver[j];
49             ans+=(num[i]-1)*(num[y]-1);//减掉父亲连向儿子这一条边,避免重复运算 
50             p=sum[i]&sum[y];//统计有多少个1,即三元环的个数 
51             ans-=p.count();
52         }
53     }
54     printf("%lld\n",ans);
55     return 0;
56 }








原文地址:https://www.cnblogs.com/nlyzl/p/11819254.html