天梯赛自主练习4补题 (如果20年去打有机会拿国二吧,国一不太可能,最后俩题都好难啊)

题目

l2-4网红打卡攻略
题意: 略。
思路: 按给定的序列模拟一下即可,如果某个点出现次数不为1,说明不符合条件,或者中间存在点不可达。忘了把不符合条件的情况设为INF,wa了半天。
时间复杂度: O(k*n)
代码:

#include
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 502;
#define int long long
const int INF = 1e12;
int n,m,k,T;
int a[N][N];
int ans[N];
int vis[N];
int tot;
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define mem(a,x) memset(a,x,sizeof(a))
bool check()
{
	for(int i=1;i<=n;++i)
	{
		if(vis[i] != 1) return 0;
	}
	return 1;
}
void solve()
{
	cin>>n>>m;
	fir(i,0,n)
	{
		fir(j,0,n)
		{
			if(i==j) a[i][j] = 0;
			else a[i][j] = INF;
		}
	}
	for(int i=0;i<m;++i)
	{
		int x,y,z; cin>>x>>y>>z;
		a[x][y] = a[y][x] = z;
	}
	cin>>k;
	int idx = 1;
	for(int t=1;t<=k;++t)
	{
		int num; cin>>num;
		vector<int> vv;
		vv.push_back(0);
		for(int i=1;i<=n;++i) vis[i] = 0;
		while(num--)
		{
			int x; cin>>x;
			vis[x]++;
			vv.push_back(x);
		}
		if(!check()) 
		{
			ans[t] = INF;
			continue;
		}
		vv.push_back(0);
		for(int i=1;i<vv.size();++i)
		{
			int l = vv[i-1];
			int r = vv[i];
			if(a[l][r] == INF)
			{
				// cout<
				ans[t] = INF;
				break;
			}
			else ans[t] += a[l][r];
		}
		if(ans[t] == INF) continue;
		tot++;
		if(ans[t] < ans[idx]) idx = t;
	}
	cout<<tot<<"\n";
	cout<<idx<<" "<<ans[idx];
}
signed main(void)
{
	solve();
	return 0;
}

l3-1 那就别担心了。
题意: 给定n个点m条边的有向图,统计从st到ed的路径数有多少,并且判断从st开始的路径是否均以ed为终点。
思路: 记忆化搜索即可。如果不记忆化的话会T。终点的方案数默认为1,每个点的方案数是所有儿子的方案数之和。可以发现有很多点的方案数会重复计算,尤其是存在环的情况下。
时间复杂度: O(能过)
代码:

#include
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 522;
int n,m,k,T;
vector<int> va[N];
int ans = 0;
bool flag = 1;
int st,ed;
bool vis[N];
int f[N];
int dfs(int cur)
{
	vis[cur] = 1;
	if(f[cur]) return f[cur];
	for(int i=0;i<va[cur].size();++i)
	{
		int j = va[cur][i];
		f[cur] += dfs(j);
	}
	return f[cur];
}
void solve()
{
	cin>>n>>m;
	for(int i=0;i<m;++i)
	{
		int x,y; cin>>x>>y;
		va[x].push_back(y);
	}
	cin>>st>>ed;
	f[ed] = 1;
    ans = dfs(st);
    cout<<ans<<" ";
    for(int i=1;i<=n;++i)
    {
    	if(vis[i] && !f[i])
    	{
    		flag = 0;
    	}
    }
    if(flag) cout<<"Yes";
    else cout<<"No";	
}
signed main(void)
{
	solve();
	return 0;
}

你可能感兴趣的:(天梯赛,自主练习,c++)