牛客訓練賽40 A,C

。。。謹以此篇,紀念我的爆0(wa~~~~TT!!!)

A:

思路:想到了應該用dp做,想用數位。可是狀態轉移方程寫不出。。。

其實簡單的。。。d[i][j][k](//表示當前爲第i位,最後兩個是j,k)=can[l][j][k]*d[i-1][l][j],(l遍歷1,49);

代碼如下:

/*

*/
#define LOCAL
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#include<vector>
#include<set>
using namespace std;
#define maxn 3000000
#define inf 40000000
#define LL long long
LL d[505][50][50];//現在第i位,i位爲j,i-1位爲k
int can[50][50][50];//不合法爲0,合法爲1 
int mod=1e9+7;
int main()
{
	#ifdef LOCAL
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	#endif
    int n,q;
    scanf("%d%d",&n,&q);
    int a,b,c;
    int i,j,k,u;
    for(i=0;i<50;i++)
        for(j=0;j<50;j++)
            for(k=0;k<50;k++)
                can[i][j][k]=1;
    LL ans=0;
    while(q--)
    {
        scanf("%d%d%d",&a,&b,&c);
        can[a][b][c]=0;
        can[a][c][b]=0;
        can[b][a][c]=0;
        can[b][c][a]=0;
        can[c][a][b]=0;
        can[c][b][a]=0;
    }
    for(int i=1;i<=2;i++)
    	for(int j=1;j<50;j++)
    		for(int k=1;k<50;k++)
    			d[i][j][k]=1;
    for(int i=3;i<=n;i++)
    {
    	for(int j=1;j<50;j++)
    	{
    		for(int k=1;k<50;k++)
    		{
    			for(int l=1;l<50;l++)
    			{
    				d[i][j][k]+=can[l][j][k]*d[i-1][l][j];
					//最後兩位爲j,k時,倒數第三位l一定要滿足(l,j,k)合法,如果合法加上i-1位時,最後兩位是l,j的情況 
    				d[i][j][k]%=mod;
    			}
    			
    		}
    	} 
    }
    for(int i=1;i<50;i++)
    for(int j=1;j<50;j++)
    ans+=d[n][i][j],ans%=mod;
    cout<< ans%mod <<endl;
    
    
    
    
    
    
    
	return 0;
}

C:從一個點出發,到終點,要遍歷每一條邊,並且每條邊只走一次,那麼主路(從起點到終點的路徑)只走一次,別的遍歷路徑都要走兩次;也就是要讓主路最長(樹的直徑);

代碼如下:

/*
c: 只有一條路徑可以只走一次,別的都要走兩次,所以選最長的路徑走一次,別的走兩次
ans=邊權和*2-直徑 
*/
#define LOCAL
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#include<vector>
#include<set>
using namespace std;
#define maxn 3000000
#define inf 40000000
#define LL long long
vector<int > G[maxn];//鄰接表
struct nod
{
	int u,v,w;
}edge[maxn];//邊 
bool vis[maxn];//判斷i點是否遍歷過
int maxx=0;//距1點最遠點
LL len;//當前長度
int len_max; 
void dfs(int now)
{
	int flag=0;//沒有出邊,即到達終點
	int l=G[now].size();
	for(int i=0;i<l;i++)
	{
		if(!vis[edge[G[now][i]].v])
		{
			vis[edge[G[now][i]].v]=1;
			len+=edge[G[now][i]].w;
			dfs(edge[G[now][i]].v);
			vis[edge[G[now][i]].v]=0;
			len-=edge[G[now][i]].w;
			flag++;
		}
	} 
	if(flag==0)
	{
		if(len>len_max)
		{
			len_max=len;
			maxx=now;
		}
	}
}
int main()
{
	#ifdef LOCAL
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	#endif
    int n,u,v,w;
    LL ans=0;
    cin>>n;
    for(int i=0;i<n-1;i++)
    {
    	cin>>edge[i].u>>edge[i].v>>edge[i].w;
    	edge[i+n].u=edge[i].v,edge[i+n].v=edge[i].u,edge[i+n].w=edge[i].w;
    	G[edge[i].u].push_back(i);//u的出邊 
    	G[edge[i].v].push_back(i+n);//v的出邊 
    	ans+=edge[i].w;
	} 
	vis[1]=1;
	dfs(1); 
	LL len1=len_max;
	memset(vis,0,sizeof(vis));
	vis[maxx]=1;
	len=0;
	len_max=0;
	dfs(maxx);
	LL len2=len_max;
	//cout<<len1<<" "<<len2<<endl;
	cout<<ans*2-len2<<endl;
    
    
    
    
    
    
    
	return 0;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章