比较有意思的一道题
存到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
n−1 条边在最短路上,因此最多跑
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;
}