22/6/30

1,acwing 164.可达性统计;2, Decorating the Pastures;3, Perimeter


1,可达性统计; 

 思路:设f[x]表示x能到达的点的个数,

那么f[x]=(x)||f(y1)||f(y2)||....   (’||‘就是或运算,y1,y2是存在有向边的(x,y1)...);

因此,要求f[x]就要知道后面的f[y1],f[y2]..所以就要按拓扑排序的逆序来做;

在表示x能否到i,可以用状态压缩,但是数据很长不是32位,就用到了bitset;

也就是将状态压缩不局限int来表示,而是可定长度的01数组来表示,并且 支持位运算;

一般来说是bitset<N>f[N],f[i]代表一串01字符(一行),第i位是1就表示能到;

f[i][i]就是本身;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for( int i=a;i<n;++i) 
#define rep2(i,a,n) for( int i=a;i<=n;++i) 
#define per1(i,n,a) for( int i=n;i>a;i--) 
#define per2(i,n,a) for( int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<long long,long long>PLL;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef double dob; 
const int N=3e4+10;
int e[N],ne[N],h[N],idx;
int d[N];
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int n,m;
vector<int>xl;
bitset<N>f[N];
void topsort()
{
    queue<int>q;
    rep2(i,1,n)if(!d[i])q.push(i);
    while (q.size())
    {
        int t=q.front();
        q.pop();
        xl.pb(t);
        for(int i=h[t];~i;i=ne[i])
        {
            int j=e[i];
            if(--d[j]==0)
            {
                q.push(j);
            }
        }
    }
    
}
signed main()
{
    quick_cin();
    cin>>n>>m;
    memset(h,-1,h);
    while(m--)
    {
        int a,b;
        cin>>a>>b;
        add(a,b);
        d[b]++;
    }
    topsort();
    per2(i,n-1,0)
    {
        int j=xl[i];
        f[j][j]=1;
        for(int k=h[j];~k;k=ne[k])
        {
            f[j]|=f[e[k]];
        }
    }
    rep2(i,1,n)cout<<f[i].count()<<endl;
    return 0;
}

2, Decorating the Pastures

题意:

n个牧场,m条双向道路连接,现给每个牧场插旗,有F和J两种,规定一条道路连接的两个牧场不能插同一种,求J最大的数,如果没有输出-1;

思路:不知道有没有孤立点,就遍历每个牧场,遍历过的标记,然后开始插旗,差的时候下一层和父亲不能一样,判断没有方案就是父亲和孩子插的旗一样;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for( int i=a;i<n;++i) 
#define rep2(i,a,n) for( int i=a;i<=n;++i) 
#define per1(i,n,a) for( int i=n;i>a;i--) 
#define per2(i,n,a) for( int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<int,int> PII;
typedef pair<long long,long long>PLL;
typedef pair<int,PII> PIII;
typedef long long LL;
typedef double dob;
int n,m;
const int N=1e6+10;
int e[N],ne[N],h[N],idx;
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int numj1,numj2;
int st[N];
bool ispf=0;
void bfs1(int x)
{
    queue<int>q;
    q.push(x);
    st[x]=1;
    numj1++;
    int f=1;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        for(int i=h[t];~i;i=ne[i])
        {
            int j=e[i];
            if(!st[j])
            {
                q.push(j);
                if(st[t]==1)st[j]=2,numj2++;
                if(st[t]==2)st[j]=1,numj1++;
            } 
            else
            {
                if(st[j]==st[t])
                {
                    ispf=1;
                    return;
                }
            }
        }
    }
}
int ans;
signed main()
{
    quick_cin();
    memset(h,-1,h);
    cin>>n>>m;
    while(m--)
    {
        int a,b;
        cin>>a>>b;
        add(a,b),add(b,a);
    }
    
    rep2(i,1,n)
    {
        if(!st[i])
        {
            numj1=0,numj2=0;
            bfs1(i);
            if(ispf)
            {
                cout<<-1;
                return 0;
            }
            ans+=max(numj1,numj2);
        }
    }
    cout<<ans;
    return 0;
}

3, Perimeter

dfs搜索最外边周长;

注意set的用法;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for( int i=a;i<n;++i) 
#define rep2(i,a,n) for( int i=a;i<=n;++i) 
#define per1(i,n,a) for( int i=n;i>a;i--) 
#define per2(i,n,a) for( int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<long long,long long>PLL;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef double dob; 
set<PII>s,vis;
int n;
int ans;
bool ishole(int x,int y)
{
    rep2(i,-1,1)
    rep2(j,-1,1)
    {
        if(s.count(make_pair(x+i,y+j))==1)return 0;
    }
    return 1;
}
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
void dfs(int x,int y)
{
    if(s.count(make_pair(x,y)))
    {
        ans++;
        return;
    }
    if(vis.count(make_pair(x,y)))return;
    vis.insert(make_pair(x,y));
    if(ishole(x,y))return;
    rep1(i,0,4)
    {
        dfs(x+dx[i],y+dy[i]);
    }
}
signed main()
{
    quick_cin();
    cin>>n;
    while (n--)
    {
        int x,y;
        cin>>x>>y;
        s.insert(make_pair(x,y));
    }
    auto st=*s.begin(); 
    dfs(st.first-1,st.second-1);
    cout<<ans;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dull丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值