思路: 就是搜索,但是用val[]验证结果是我没想到的
trick :
vector>a、vector>a[3]、vector>> a、vector>a
这些容器的区别,具体一些api类似clear,emplace,push_back这种可以去查文档#include
#include
#include
#include
#include
#include
using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5;
vector<pii> adj[N];
int vis[N], val[N];
void dfs(int u)
{
vis[u] = 1;
int sz = adj[u].size();
for (auto x : adj[u])
{
int v = x.first, w = x.second;
if (vis[v] == 0)
{
val[v]= w + val[u];
dfs(v);
}
}
}
void solve()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++ i)
{
adj[i].clear();
vis[i] = 0, val[i] = 0;
}
vector<array<int, 3>> c;
for (int i = 1; i <= m; ++ i)
{
int a, b, d;
cin >> a >> b >> d;
adj[a].push_back({b, d});
adj[b].push_back({a, -d});
c.push_back({a, b, d});
}
for (int i = 1; i <= n; ++ i)
{
if (vis[i] == 0) dfs(i);
}
for (int i =1; i <= m; ++ i)
{
int a = c[i - 1][0], b = c[i - 1][1], d = c[i - 1][2];
if (val[a] + d != val[b] )
{
cout << "NO" << endl;
return ;
}
}
cout << "YES" << endl;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin >> T;
while (T --) solve();
return 0;
}
题意在这
trick:
#include
using namespace std;
typedef pair<int, int> pii;
void solve()
{
int n;
cin >> n;
vector<vector<pii>> edges(n + 1);
for (int i = 1; i < n; ++ i)
{
int u, v; cin >> u >> v;
edges[u].push_back({v, i}), edges[v].push_back({u, i});
}
bool ok = true;
vector<int> sz(n + 1);
vector<int> ans;
//idx指的是由哪条边找到当前点的
function<void(int, int, int)> dfs = [&](int u, int fa, int idx)
{
sz[u] = 1;
for (auto [v, idx] : edges[u])
{
if (v == fa) continue;
else
{
dfs(v, u, idx);
sz[u] += sz[v];
}
}
if (sz[u] > 3)
{
ok = false;
return ;
}
else if (sz[u] == 3)
{
sz[u] = 0;
if (idx != 0) ans.push_back(idx);//u = 1的时候一条边都不需要剪
}
};
dfs(1, 0, 0);
ok &= !sz[1];//根节点所在的联通块为0才说明当前树全被剪完了
if (ok)
{
cout << ans.size() << endl;
for (auto idx : ans) cout << idx << " ";
cout << endl;
}
else cout << -1 << endl;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin >> T;
while (T --) solve();
return 0;
}
这题好像要用线段树,主席树啥的,题解在洛古有,很清楚。。我要去补提高课了。
题意:
两个操作把当前的字符串变成一个非递减的字符串
#include
using namespace std;
typedef pair<int, int> pii;
const long long pw10 = 1e12;
void solve()
{
string s;
cin >> s;
long long ans = 1e18;
int cnt0 = 0, cnt1 = count(s.begin(), s.end(), '1');
//cnt0表示当前位置之前有多少0,cnt1表示当前位置之后有多少1
int n = s.size();
if (n == 1) ans = 0;
for (int i = 0; i < n - 1; ++ i)
{
if (s[i] == '0') cnt0 ++;
else cnt1 --;
int k = cnt0 + cnt1 + (s[i] == '1') + (s[i + 1] == '0');
long long cur = 0;
cur = (n - k) * (pw10 + 1);
if (s[i] > s[i + 1]) cur += pw10;
ans = min(cur, ans);
}
cout << ans << endl;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin >> T;
while (T --) solve();
return 0;
}
trick:
我大概总结了一下:
#include
using namespace std;
typedef pair<int, int> pii;
int ask(int x)
{
cout << "- " << x << endl;
cout.flush();
int t_cnt; cin >> t_cnt;
return t_cnt;
}
void solve()
{
int cnt; cin >> cnt;
int last = 1;
int ans = 0;
while (cnt)
{
int t_cnt = ask(last);//减last的目的其实就是让n'最后一个1和第0位之间全部变成1,这样我们就知道最后1位1所在的位置了
last = (1 << (t_cnt - cnt + 1));//t - cnt + 1获得当前n'的最后一个1和第0位的距离
ans |= last;// |=就是+=
cnt -- ;
}
cout << "! " << ans << endl;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin >> T;
while (T --) solve();
return 0;
}