ABC 218 C、D(思维 E(最小生成树 F(最短路

C - Shapes

比较有意思的一道题
存到vector一个一个匹配就行

code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e2 + 9;
const ll mod = 998244353;
const ll inf = 0x3f3f3f3f;
ll n, m, k;
ll sum = 0;
char s[maxn][maxn], t[maxn][maxn];
char m2[maxn][maxn],m3[maxn][maxn], m4[maxn][maxn];
vector <pair<int,int> > vt;
bool check(char a[][maxn])
{
	vector <pair<int,int> > va;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			if(a[i][j] == '#')
				va.push_back({i, j});
	if(va.size() != vt.size()) return false;
	else 
	{
		int mx = va[0].first - vt[0].first, my = va[0].second - vt[0].second;
		for(int i = 1; i < va.size(); ++i)
		{
			if(va[i].first - vt[i].first != mx ||  va[i].second - vt[i].second != my)
				return false;
		}
		return true;
	}
}
void work()
{
	cin >> n;
	for(int i = 1; i <= n; ++i)
		cin >> (s[i] + 1);
	for(int i = 1; i <= n; ++i)
	{
		cin >> (t[i] + 1);
		for(int j = 1; j <= n; ++j)
			if(t[i][j] == '#')
				vt.push_back({i, j});
	}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			m2[i][n-j+1] = s[j][i];
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			m3[i][n-j+1] = m2[j][i];		
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			m4[i][n-j+1] = m3[j][i];
			
	if(check(s) || check(m2) || check(m3) || check(m4))
		cout << "Yes\n";
	else cout << "No\n";
}

int main()
{
	ios::sync_with_stdio(0);
	//int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

D - Rectangles
题意:给你 n n n 个点,找这 n n n 个点能组成多少矩阵
思路:找矩阵对角线,标记已经找过的对角线
code:
(map太慢了)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e3 + 9;
const ll mod = 998244353;
const ll inf = 0x3f3f3f3f;
ll n, m, k;
struct node
{
	int x, y;
}a[maxn];
map <pair<int,int>, int> ma;
void work()
{
	cin >> n;
	for(int i = 1; i <= n; ++i)
	{
		cin >> a[i].x >> a[i].y;
		ma[{a[i].x, a[i].y}] = 1;
	}
	int sum = 0;
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= n; ++j)
		{
			if(!(a[i].x < a[j].x && a[i].y < a[j].y)) continue;
			if(i != j && a[i].x != a[j].x && a[i].y != a[j].y)
			{
				pair<int,int> t1 = {a[i].x, a[j].y}, t2 = {a[j].x, a[i].y};
				if(ma[t1] && ma[t2]) 	++sum;
 			}
		}
	}
	cout << sum<< endl;
}

int main()
{
	//ios::sync_with_stdio(0);
	//int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

vector存坐标,用 b i n a r y binary binary_ s e a r c h search search 判断是否出现比 m a p map map 快的多的多
code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e3 + 9;
const ll mod = 998244353;
const ll inf = 0x3f3f3f3f;
ll n, m, k;

void work()
{
	cin >> n;
	vector <pair<int,int> > v(n);
	for(int i = 0; i < n; ++i)
		cin >> v[i].first >> v[i].second;
	sort(v.begin(), v.end());
	int sum = 0;
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < n; ++j) if(v[i].first < v[j].first && v[i].second < v[j].second)
		{
			bool f1 = binary_search(v.begin(), v.end(), make_pair(v[i].first, v[j].second));
			bool f2 = binary_search(v.begin(), v.end(), make_pair(v[j].first, v[i].second));
			if(f1 && f2) ++sum;
		}
	cout << sum << endl;
}

int main()
{
	ios::sync_with_stdio(0);
	//int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

E - Destruction
最小生成树,很水的一道题,比C、D都简单
code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5 + 9;
const ll mod = 998244353;
const ll inf = 0x3f3f3f3f;
ll n, m, k;
ll f[maxn];
ll sum = 0;
struct node
{
	ll x, y, w;
	bool operator<(const node &B)const{
		return w < B.w;
	}
}e[maxn];
ll find(ll x)
{
	return x == f[x] ? x : f[x] = find(f[x]);
}
void work()
{
	cin >> n >> m;
	for(int i = 1; i <= m; ++i)
	{
		cin >> e[i].x >> e[i].y >> e[i].w;
		//if(e[i].w >= 0) sum += e[i].w;
	}
	for(ll i = 1; i <= n; ++i) f[i] = i;
	sort(e + 1, e + 1 + m);
	ll cnt = 0;
	ll pos = m + 1;
	for(int i = 1; i <= m; ++i)
	{
		ll xx = find(e[i].x), yy = find(e[i].y);
		if(xx != yy)
		{
			f[xx] = yy;
			++cnt;
			if(cnt == n - 1)
			{
				pos = i + 1;
				break;
			}
		}
		else if(e[i].w >= 0) sum += e[i].w;
	}
	//cout << pos << endl;
	for(int i = pos; i <= m; ++i)
	{
		if(e[i].w >= 0) sum += e[i].w;
	}
	cout << sum << endl;
}

int main()
{
	//ios::sync_with_stdio(0);
	//int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

F - Blocked Roads
题意:删去第 i i i 个边时, 1 − > n 1->n 1>n 的最短路是多少
思路:
先跑一边最短路,标记最短路上的所有边
然后如果删的边不在最短路上,就输出最短路,不然就跑一遍最短路
n − 1 n-1 n1 条边在最短路上,因此最多跑 n n n 次,复杂度 n ( n l o g n ) n(nlogn) n(nlogn)
(好像也挺水的
code:
(这个代码有点问题,也能过,存的不全是1到n的最短路上的边,如果出现 1到2,1到3,1到4…1到n的最短路没有一条边是重复的,并且都是 i i i 条,这种比较极端的数据应该就会T)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5 + 9;
const ll mod = 998244353;
const ll inf = 0x3f3f3f3f;
ll n, m, k;

int dis[409], vis[409];
int ans[maxn];
struct edge
{
	int w, to, next;
}e[maxn];
int head[maxn], cnt;
void add(int x, int y)
{
	e[++cnt].w = 1;
	e[cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
map <pair<int,int>, int> ma;
int dij(int nx, int ny)
{
	memset(vis, 0, sizeof(vis));
	for(int i = 1; i <= n; ++i) dis[i] = inf;
	dis[1] = 0;
	priority_queue <pair<int,int>, vector<pair<int,int> > , greater<pair<int,int> > > q;
	q.push({0, 1});
	while(!q.empty())
	{
		int now = q.top().second;
		q.pop();
		if(vis[now]) continue;
		vis[now] = 1;
		for(int i = head[now]; i; i = e[i].next)
		{
			int tmp = e[i].to;
			if(!vis[tmp] && dis[tmp] > dis[now] + e[i].w && !(now==nx&&tmp==ny))
			{
				ma[{now, tmp}] = 1;
				dis[tmp] = dis[now] + e[i].w;
				q.push({dis[tmp], tmp});
			}
		}
	}
	return dis[n] == inf ? -1 : dis[n];
}
void work()
{
	cin >> n >> m;
	vector <pair<int,int> > v(m + 1);
	for(int i = 0; i < m; ++i)
	{
		cin >> v[i].first >> v[i].second;
		add(v[i].first, v[i].second);
	}
	int Min = dij(0, 0);
	for(int i = 0; i < m; ++i)
	{
		if(ma[{v[i].first, v[i].second}])
			ans[i+1] = dij(v[i].first, v[i].second);
		else ans[i+1] = Min;
	}
	
	for(int i = 1; i <= m; ++i)
		cout << ans[i] << endl;
}

int main()
{
	ios::sync_with_stdio(0);
	//int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

开一个 p r e pre pre 数组存路径,倒着找 1 1 1 n n n 的最短路
(这个代码跑的就比上一个快两倍)
code2:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5 + 9;
const ll mod = 998244353;
const ll inf = 0x3f3f3f3f;
ll n, m, k;

int dis[409], vis[409];
int ans[maxn];
struct edge
{
	int w, to, next;
}e[maxn];
int head[maxn], cnt;
void add(int x, int y)
{
	e[++cnt].w = 1;
	e[cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
int pre[409];// 存路径 
int dij(int nx, int ny)
{
	memset(vis, 0, sizeof(vis));
	for(int i = 1; i <= n; ++i) dis[i] = inf;
	dis[1] = 0;
	priority_queue <pair<int,int>, vector<pair<int,int> > , greater<pair<int,int> > > q;
	q.push({0, 1});
	while(!q.empty())
	{
		int now = q.top().second;
		q.pop();
		if(vis[now]) continue;
		vis[now] = 1;
		for(int i = head[now]; i; i = e[i].next)
		{
			int tmp = e[i].to;
			if(!vis[tmp] && dis[tmp] > dis[now] + e[i].w && !(now==nx&&tmp==ny))
			{
				dis[tmp] = dis[now] + e[i].w;
				pre[tmp] = now;
				q.push({dis[tmp], tmp});
			}
		}
	}
	return dis[n] == inf ? -1 : dis[n];
}
void work()
{
	cin >> n >> m;
	vector <pair<int,int> > v(m + 1);
	for(int i = 0; i < m; ++i)
	{
		cin >> v[i].first >> v[i].second;
		add(v[i].first, v[i].second);
	}
	int Min = dij(0, 0);
	if(Min == -1){// 一开始跑不出来必须特判掉,不然下边原路返回永远不会终止 
		for(int i = 0; i < m; ++i)
			cout << -1 << endl;return;
	}
	vector <pair<int,int> > mark;	
	int pos = n;
	while(pos != 1)// 倒着找路
	{
		mark.push_back({pre[pos], pos});
		pos = pre[pos];
	}
	sort(mark.begin(), mark.end());
	for(int i = 0; i < m; ++i)
	{
		bool f = binary_search(mark.begin(), mark.end(), make_pair(v[i].first, v[i].second));
		if(f)
			ans[i+1] = dij(v[i].first, v[i].second);
		else ans[i+1] = Min;
	}
	
	for(int i = 1; i <= m; ++i)
		cout << ans[i] << endl;
}

int main()
{
	//ios::sync_with_stdio(0);
	//int TT;cin>>TT;while(TT--)
	work();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值