2019秦皇岛补题

F题(dfs判环)

链接:https://codeforces.com/gym/102361/problem/F
思路 如果环的边长为k,那么环的删边方案数是2k-1。如果链的边长为k,那么链的删边方案数是2k。环的方案数乘以链的方案数就是总的方案数
(之前没关同步wa了。。。)
代码

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring> 
using namespace std;
const int maxn=3e5+10;
const int mod=998244353;
#define ll long long 
int n,m,cnt,tot;
ll ans;
vector<int>G[maxn];
int vis[maxn],deep[maxn];
ll power(ll a,ll b)
{
	ll ans=1,x=a;
	for(;b;b>>=1)
	{
		if(b&1)
		{
			ans=ans*x%mod;
		}
		x=x*x%mod;
	}
	return ans;
}
void dfs(int u,int fa)
{	
	deep[u]=deep[fa]+1;
	for(int i=0;i<G[u].size();i++)
	{
		if(G[u][i]!=fa)
		{
			if(!vis[G[u][i]])
			{
				vis[G[u][i]]=1;
				dfs(G[u][i],u);
			}
			else if(deep[G[u][i]]<deep[u])
			{
				int x=deep[u]-deep[G[u][i]]+1;
				tot-=x;
				ans=ans*(power(2,x)-1)%mod;
			}
		}
		
	}
}
int main()
{
		int u,v;	
		ios::sync_with_stdio(false);
		cin>>n>>m;
		ans=1,tot=m;
		for(int i=1;i<=m;i++)
		{
			int u,v;
			cin>>u>>v;
			G[u].push_back(v);
			G[v].push_back(u); 
		}
		for(int i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				vis[i]=1;
				dfs(i,i);
			}
		}
		ans=ans*power(2,tot)%mod;
		cout<<ans<<"\n";
	
	return 0;
}

I 题(状态压缩dp)

链接:https://codeforces.com/gym/102361/problem/I
思路:暴力dp跑6种情况,每种情况都看前一个状态的6种情况,看这个状态与前面一个状态相同的字母与多少相同,复杂度O(36*n)
状态方程dp[i][k]=min(dp[i][k],dp[i-1][k]+solve(mn[s[i-1]],mn[s[i]],j,k)。i是当前状态,k表示6种情况的其中一种,j代表上一个状态下的6种情况,solve()函数表示这个状态与上一个状态的尾部与多少相同的字母。
代码

#include<bits/stdc++.h>
using namespace std;
char a[10][6][4]=
{
    {{"QQQ"},{"QQQ"},{"QQQ"},{"QQQ"},{"QQQ"},{"QQQ"}},
    {{"QQW"},{"QQW"},{"QWQ"},{"QWQ"},{"WQQ"},{"WQQ"}},
    {{"QQE"},{"QQE"},{"EQQ"},{"EQQ"},{"QEQ"},{"QEQ"}},
    {{"WWW"},{"WWW"},{"WWW"},{"WWW"},{"WWW"},{"WWW"}},
    {{"WWQ"},{"WWQ"},{"WQW"},{"WQW"},{"QWW"},{"QWW"}},
    {{"WWE"},{"WWE"},{"WEW"},{"WEW"},{"EWW"},{"EWW"}},
    {{"EEE"},{"EEE"},{"EEE"},{"EEE"},{"EEE"},{"EEE"}},
    {{"EEQ"},{"EEQ"},{"EQE"},{"EQE"},{"QEE"},{"QEE"}},
    {{"WEE"},{"WEE"},{"EWE"},{"EWE"},{"EEW"},{"EEW"}},
    {{"QWE"},{"QEW"},{"WEQ"},{"WQE"},{"EQW"},{"EWQ"}}
};
map<char,int>mn;
int dp[100010][6];
char s[100010];
int solve(int s,int t,int f,int g)
{
    if(a[s][f][0]==a[t][g][0]&&a[s][f][1]==a[t][g][1]&&a[s][f][2]==a[t][g][2])
        return 0;
    else if(a[s][f][2]==a[t][g][1]&&a[s][f][1]==a[t][g][0])
        return 1;
    else if(a[s][f][2]==a[t][g][0])
        return 2;
    return 3;
}
int main()
{
    scanf("%s",s);
    mn['Y']=0,mn['V']=1,mn['G']=2,mn['C']=3,mn['X']=4,mn['Z']=5,mn['T']=6,mn['F']=7,mn['D']=8,mn['B']=9;
    int ans=strlen(s);
    memset(dp,0x3f3f3f,sizeof(dp));
    for(int i=0;i<6;i++)
    {
        dp[0][i]=3;
    }
    for(int i=1;i<ans;i++)
    {
        for(int j=0;j<6;j++)
        {
            for(int k=0;k<6;k++)
            {
                dp[i][k]=min(dp[i][k],dp[i-1][j]+solve(mn[s[i-1]],mn[s[i]],j,k));
            }
        }
    }
    int res=2e9;
    for(int i=0;i<6;i++)
    {
        res=min(res,dp[ans-1][i]);
    }
    res+=ans;
    cout<<res<<"\n";
    return 0;
}

posted @ 2019-10-31 01:15  hh13579  阅读(214)  评论(0)    收藏  举报