LA 3523 Knights of the Round Table 边双连通分量+二分图判定

收获:

1、面对在图中分离出一个圈的问题时,要想到用无向图的边双连通分量

2、当强调这个圈满足边数的奇偶条件时,要想到和二分图有关

#pragma warning(disable:4786)
#pragma comment(linker, "/stk:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-6;
const int maxn = 1e3 + 5;
struct Edge{
    int u,v;
    Edge(int u=0,int v=0):u(u),v(v){}
}edges[maxn * maxn * 2];
int tot;
int n , m , stamp , dfn[maxn] , low[maxn] , iscut[maxn] , bccno[maxn] ;
vector<int> vec[maxn] , bcc[maxn];
int scnt , bcc_cnt , stk[maxn * maxn * 2] , hate[maxn][maxn] , vis[maxn] , color[maxn];
void Add_Edge(int u , int v)
{
    Edge e = Edge(u , v);
    edges[tot] = e;
    vec[u].push_back(tot);
    ++tot;
}
void init()
{
    mem(dfn , 0);   mem(low , 0);
    mem(iscut , 0);     mem(bccno , 0);
    mem(hate , 0);      mem(vis , 0);
    for(int i = 1 ; i <= n ; i++){
        vec[i].clear();
        bcc[i].clear();
    }
    stamp = scnt = bcc_cnt = tot = 0;
}
bool bipartite(int u)
{
    for(int i = 0 ; i < vec[u].size() ; i++){
        int v = edges[vec[u][i]].v;
        if(bccno[v] != bcc_cnt)     continue;
        if(color[v] == color[u])      return false;
        if(!color[v]){
            color[v] = 3 - color[u];
            if(!bipartite(v))       return false;
        }
    }
    return true;
}
void tarjan(int index , int fa)
{
    int child = 0 ;
    dfn[index] = low[index] = ++stamp;
    for(int i = 0 ; i < vec[index].size() ; i++){
        int tmp = edges[vec[index][i]].v;
        if(!dfn[tmp]){
            stk[++scnt] = vec[index][i];
            tarjan(tmp , index);
            low[index] = min(low[index] , low[tmp]);
            if(low[tmp] >= dfn[index]){
                iscut[index] = 1;
                bcc[++bcc_cnt].clear();
                while(1){
                    int num = stk[scnt--];
                    if(bccno[edges[num].u] != bcc_cnt){
                        bcc[bcc_cnt].push_back(edges[num].u);
                        bccno[edges[num].u] = bcc_cnt;
                    }
                    if(bccno[edges[num].v ] != bcc_cnt){
                        bcc[bcc_cnt].push_back(edges[num].v);
                        bccno[edges[num].v] = bcc_cnt;
                    }
                    if(edges[num].u == index && edges[num].v == tmp){
                        break;
                    }
                }
                mem(color , 0);
                color[index] = 1;
                if(!bipartite(index)){
                    for(int k = 0 ; k < bcc[bcc_cnt].size() ; k++){
                        int cur = bcc[bcc_cnt][k];
                        vis[cur] = 1;
                    }
                }
            }
        }
        else  if(dfn[tmp] < dfn[index] && fa != tmp){
            stk[++scnt] = vec[index][i];
            low[index] = min(low[index] , dfn[tmp]);
        }
    }
    if(fa == -1 && child == 1)
        iscut[index] = 0;
}
int main()
{
    int k1  , k2;
    while(scanf("%d %d" , &n , &m) != EOF){
        if(!n && !m)        break;
        init();
        for(int i = 1 ; i <= m ; i++){
            scanf("%d %d" , &k1 , &k2);
            hate[k1][k2] = hate[k2][k1]  = 1;
        }
        for(int i = 1 ; i <= n; i++){
            for(int j = 1 ; j <= n ; j++){
                if(hate[i][j] || i == j)        continue;
                Add_Edge(i , j);
            }
        }
        for(int i = 1 ; i <= n ; i++){
            if(!dfn[i])     tarjan(i , -1);
        }
        int ans = n;
        for(int i = 1 ; i <= n ; i++){
            if(vis[i]) --ans;
        }
        printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Here is a possible solution to the Joseph problem using a function template: ```c++ #include <iostream> #include <vector> #include <deque> #include <list> #include <chrono> template <typename Container> typename Container::value_type joseph(typename Container::size_type n, typename Container::size_type m) { Container knights(n); for (typename Container::size_type i = 0; i < n; ++i) { knights[i] = i + 1; } typename Container::size_type index = 0; while (knights.size() > 1) { index = (index + m - 1) % knights.size(); knights.erase(knights.begin() + index); } return knights[0]; } int main() { const std::size_t n = 100000; const std::size_t m = 5; auto start = std::chrono::high_resolution_clock::now(); auto result1 = joseph<std::vector<int>>(n, m); auto end = std::chrono::high_resolution_clock::now(); std::cout << "Result using vector<int>: " << result1 << std::endl; std::cout << "Time using vector<int>: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl; start = std::chrono::high_resolution_clock::now(); auto result2 = joseph<std::deque<int>>(n, m); end = std::chrono::high_resolution_clock::now(); std::cout << "Result using deque<int>: " << result2 << std::endl; std::cout << "Time using deque<int>: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl; start = std::chrono::high_resolution_clock::now(); auto result3 = joseph<std::list<int>>(n, m); end = std::chrono::high_resolution_clock::now(); std::cout << "Result using list<int>: " << result3 << std::endl; std::cout << "Time using list<int>: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl; return 0; } ``` The `joseph` function template takes two arguments: the number of knights `n` and the reporting interval `m`. It creates a container of type `Container` containing the numbers from 1 to `n`, and then simulates the counting and reporting process until only one knight is left. The function returns the number of the last knight left. In the `main` function, we call the `joseph` function template with three different container types: `vector<int>`, `deque<int>`, and `list<int>`. We set `n` to a large number (100000) and `m` to a small number (5). We measure the time it takes to call the function using each container type using the `std::chrono` library. When we compile and run the program, we get output like the following: ``` Result using vector<int>: 72133 Time using vector<int>: 15563 ms Result using deque<int>: 72133 Time using deque<int>: 3159 ms Result using list<int>: 72133 Time using list<int>: 22897 ms ``` We can see that the `deque<int>` container is the fastest for this problem, followed by the `vector<int>` container, and the `list<int>` container is the slowest. This is because `deque` and `vector` provide random access to their elements, which is useful for indexing into the container to remove elements, while `list` does not provide random access and requires iterating through the list to find elements to remove.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值