codeforces 图论题目集(持续更新)

简单题,反正菜

Dasha Code Championship - SPb Finals Round (only for onsite-finalists)

A. Anadi and Domino

https://codeforces.com/problemset/problem/1210/A

思路:当Grape中节点个数少于等于6个时,最多存在15条边,每个节点赋值一个点数,所以n <= 6 时,可存在变数为m,当Grape中节点的个数为7个时,必然是存在俩个节点属于同一标记的,因此枚举每俩个节点,

如果其他节点和这俩个节点同时存在边,则这条边必然是不可取的,因为各种类型的筛子只能取一个,所以需要减去

/*
 * @Author: CY__HHH
 * @Date: 2019-10-21 12:09:09
 * @LastEditTime: 2019-10-21 12:09:09
 */
#include<bits/stdc++.h>
#define inf (0x3f3f3f3f)
typedef long long i64;
using namespace std;
const int maxn = 32;
bool Grape[maxn][maxn]; 
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n,m,u,v;    cin >> n >> m;
    for(int i=0;i!=m;++i)
    {
        cin >> u >> v;
        Grape[u][v] = Grape[v][u] = true;
    }
    int minn = inf;
    if( n <= 6)
        cout << m <<'\n';
    else{
        for(int i=1;i<=n;++i)
        {
            for(int j=i+1;j<=n;++j)
            {
                int  cnt = 0;
                for(int k=1;k<=n;++k)
                    if(Grape[i][k]&&Grape[j][k])
                        ++cnt;
                minn = min(minn,cnt);
            }
        }
        cout << m - minn << '\n';
    }
    return 0;
}

Codeforces Round #516 (Div. 1, by Moscow Team Olympiad)  B. Labyrinth

https://codeforces.com/contest/1063/problem/B

思路:记忆化bfs,因为搜索的节点的左右移的个数是有限的,因此可能先搜索到的节点并不是最优的,因此如果存在更好的状态就更新

#include<bits/stdc++.h>
#define inf (0x3f3f3f3f)
using namespace std;
const int maxn = 2e3 + 32;
char Grape[maxn][maxn];
int n,m,r,c,lt,rt;
int dis[maxn][maxn];
bool vis[maxn][maxn];
queue<pair<int,int> > q;
int arr[][4] = {1,-1,0,0,
                0,0,1,-1};
int main()
{
    ios::sync_with_stdio(false);    cin.tie(0),cout.tie(0);
    cin>>n>>m>>r>>c>>lt>>rt;
    --r,--c;
    for(int i=0;i!=n;++i)
        cin>>Grape[i];
    memset(dis,inf,sizeof(dis));
    dis[r][c] = 0;
    q.push(make_pair(r,c));
    while(!q.empty())
    {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        for(int i=0;i!=4;++i)
        {
            int nx = x + arr[0][i];
            int ny = y + arr[1][i];
            if(nx>=0&&nx<n&&ny>=0&&ny<m&&Grape[nx][ny]=='.')
            {
                if(i==3)
                {
                    if(dis[nx][ny] > dis[x][y] + 1)
                    {
                        dis[nx][ny] = dis[x][y] + 1;
                        q.push(make_pair(nx,ny));
                    }
                } 
                else
                {
                    if(dis[nx][ny] > dis[x][y])
                    {
                        dis[nx][ny] = dis[x][y];
                        q.push(make_pair(nx,ny));
                    }
                }
            }
        }
    }
    int cnt = 0;
    for(int i=0;i!=n;++i)
        for(int j=0;j!=m;++j)
        {
            if(dis[i][j] == inf)
                continue;
            int l = dis[i][j];
            int r = j + l - c;
            if(l<=lt&&r<=rt)
                ++cnt;
        }
    cout << cnt <<'\n';
}

Codeforces Round #562 (Div. 2) B. Pairs

https://codeforces.com/problemset/problem/1169/B

思路:先枚举下是否有没有相同的俩对节点,如果存在,则必定得从这俩对中各自取一个,枚举下就好了

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 32;
int a[maxn],b[maxn],c[2],d[2];
int main()
{
    int n,m;    scanf("%d%d",&n,&m);
    scanf("%d%d",&a[0],&b[0]);
    c[0] = a[0],c[1] = b[0];
    bool flag = false;
    for(int i=1;i!=m;++i)
    {
        scanf("%d%d",&a[i],&b[i]);
        if(a[i]!=c[0]&&a[i]!=c[1]&&b[i]!=c[0]&&b[i]!=c[1])
        {
            flag = true;
            d[0] = a[i],d[1] = b[i];
        }
    }
    if(!flag)
    {
        printf("YES\n");
        return 0;
    }
    for(int i=0;i!=2;++i)
    {
        for(int j=0;j!=2;++j)
        {
            flag = true;
            for(int k=0;k!=m;++k)
            {
                if(a[k]!=c[i]&&a[k]!=d[j]&&b[k]!=c[i]&&b[k]!=d[j])
                {
                    flag = false;
                    break;
                }
            }
            if(flag)
            {
                printf("YES\n");
                return 0;
            }
        }
    }
    printf("NO\n");
}

 https://codeforces.com/problemset/problem/1133/F1 

Codeforces Round #544 (Div. 3) F1. Spanning Tree with Maximum Degree

求图中节点度最大的生成树,则找出度最大的节点,由节点bfs就好了

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 32;
bool vis[maxn];
int du[maxn];
vector<int> Grape[maxn];
int main()
{
    int n,m,u,v,pos,maxx = 0;    scanf("%d%d",&n,&m);
    for(int i=0;i!=m;++i)
    {
        scanf("%d%d",&u,&v);
        ++du[u],++du[v];
        if(du[u] > maxx)
        {
            maxx = du[u];
            pos = u;
        }
        if(du[v] > maxx)
        {
            maxx = du[v];
            pos = v;
        }
        Grape[u].push_back(v);
        Grape[v].push_back(u);
    }
    queue<int> q;   q.push(pos);
    vis[pos] = true;
    while(!q.empty())
    {
        int cur = q.front();    q.pop();
        for(int i=0;i!=Grape[cur].size();++i)
        {
            int v = Grape[cur][i];
            if(vis[v])
                continue;
            printf("%d %d\n",cur,v);
            q.push(v);
            vis[v] = true;
        }
    }
}

  Codeforces Round #485 (Div. 1)A. Fair

成功贡献一发TLE后发现我不愧是和傻子

思路:因为颜色的种类情况很少,所以拿空间换时间呐,dist[node][type] 表示node节点到type需要的最少步数,将每种类型广搜就好了

/*
 * @Author: CY__HHH
 * @Date: 2019-10-21 12:09:09
 * @LastEditTime: 2019-10-22 19:11:12
 */
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 32;
bool vis[maxn];
typedef long long i64;
int main()
{
    ios::sync_with_stdio(false);    cin.tie(0),cout.tie(0);
    int n,m,s,k,u,v;    cin>>n>>m>>s>>k;
    vector<int> col(n+1);
    for(int i=1;i<=n;++i)
        cin >> col[i];
    vector<vector<int>> Grape(n+1);
    for(int i=1;i<=m;++i)
    {
        cin >> u >> v;
        Grape[u].push_back(v);
        Grape[v].push_back(u);
    }
    vector<vector<int>> dist(n+1);
    for(int i=1;i<=n;++i)
        dist[i].resize(s+1);
    for(int type = 1;type <= s;++type)
    {
        memset(vis,false,sizeof(vis));
        queue<int> seq;
        for(int i=1;i<=n;++i)
        {
            if(col[i] == type)
            {
                seq.push(i);
                dist[i][type] = 0;
                vis[i] = true;
            }
        }
        while(!seq.empty())
        {
            int cur = seq.front();
            seq.pop();
            for(auto v:Grape[cur])
            {
                if(vis[v])
                    continue;
                dist[v][type] = dist[cur][type] + 1;
                seq.push(v);
                vis[v] = true;
            }
        }
    }
    for(int i=1;i<=n;++i)
    {
        i64 sum = 0;
        sort(dist[i].begin()+1,dist[i].end());
        for(int j=1;j<=k;++j)
            sum += dist[i][j];
        cout<<sum<<" ";
    }
    cout<<'\n';
}

附上一道二分题

https://codeforces.com/problemset/problem/1251/D

贪心的策略,先将l排个序,low 为 0,high 为 1e9 + 5,去二分查找是否存在某个值mid,使得排序后的数组一定是距离mid 最近的 ,如果对应的r大于mid则sum += max(0,mid - l)

如果存在一半个,并且sum和小于等于S,则说明可行

/*
 * @Author: CY__HHH
 * @Date: 2019-10-26 13:38:55
 * @LastEditTime: 2019-10-26 17:49:26
 */
#include<bits/stdc++.h>
#define rep(i, n) for(int i=0;i!=n;++i)
#define per(i, n) for(int i=n-1;i>=0;--i)
#define Rep(i, sta, n) for(int i=sta;i!=n;++i)
#define rep1(i, n) for(int i=1;i<=n;++i)
#define per1(i, n) for(int i=n;i>=1;--i)
#define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
#define L k<<1
#define R k<<1|1
#define inf (0x3f3f3f3f)
#define llinf (1e18)
#define mid (tree[k].l+tree[k].r)>>1
#define ALL(A) A.begin(),A.end()
#define SIZE(A) ((int)A.size())
typedef long long i64;
using namespace std;
typedef struct Node{
    int l,r;
    bool operator<(const struct Node& no)const
    {
        return l < no.l;
    }
}node;
int n,Count;
i64 s;
vector<node> arr;
bool find(int Mid)
{
    i64 sum = 0;
    for(auto& v:arr)
        sum += v.l;
    int cnt = 0;
    for(int i=n-1;i>=0&&cnt<Count;--i)
    {
        if(arr[i].r >= Mid)
        {
            sum += max(0,Mid - arr[i].l);
            ++cnt;
        }
    }
    return cnt == Count&&sum <= s;
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t;  cin>>t;
    while(t--)
    {
        cin>>n>>s;
        arr.resize(n);
        Count = (n + 1) >> 1;
        for(auto& v:arr)
            cin>>v.l>>v.r;
        sort(arr.begin(),arr.end());
        int low = 0,high = 1e9 + 4 ,ans;
        while(low <= high)
        {
            int Mid  = (low + high) >> 1;
            if(find(Mid))
            {
                ans = Mid;
                low = Mid + 1; 
            }
            else
                high = Mid - 1;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

  

posted on 2019-10-21 12:57  chengyulala  阅读(474)  评论(0编辑  收藏  举报

导航