using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("6");
WillReturn.Add("5 3 2 4 6 1");
WillReturn.Add("4");
WillReturn.Add("1 5");
WillReturn.Add("5 6");
WillReturn.Add("1 2");
WillReturn.Add("2 3");
//3
//4 2 1
}
else if (InputPattern == "Input2") {
WillReturn.Add("5");
WillReturn.Add("3 4 1 2 5");
WillReturn.Add("2");
WillReturn.Add("1 3");
WillReturn.Add("2 5");
//-1
}
else if (InputPattern == "Input3") {
WillReturn.Add("4");
WillReturn.Add("1 2 3 4");
WillReturn.Add("6");
WillReturn.Add("1 2");
WillReturn.Add("1 3");
WillReturn.Add("1 4");
WillReturn.Add("2 3");
WillReturn.Add("2 4");
WillReturn.Add("3 4");
//0
//
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static int mN;
struct EdgeInfoDef
{
internal int EdgeID; // 答えで、枝番号を出力する必要あり
internal int ToNode;
}
// 隣接リスト
static Dictionary<int, List<EdgeInfoDef>> mToNodeListDict = new Dictionary<int, List<EdgeInfoDef>>();
static int[] mPArr;
static void Main()
{
List<string> InputList = GetInputList();
int[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();
SplitAct(InputList[0]);
mN = wkArr[0];
var InsUnionFind = new UnionFind();
for (int I = 0; I <= mN - 1; I++) {
InsUnionFind.MakeSet(I);
}
mPArr = InputList[1].Split(' ').Select(pX => int.Parse(pX)).ToArray();
for (int I = 0; I <= mPArr.GetUpperBound(0); I++) {
mPArr[I]--;
}
int CurrEdgeID = 0;
foreach (string EachStr in InputList.Skip(3)) {
CurrEdgeID++;
SplitAct(EachStr);
int CurrFromNode = wkArr[0] - 1;
int CurrToNode = wkArr[1] - 1;
// サイクルになる枝は、接続しない
int Root1 = InsUnionFind.FindSet(CurrFromNode);
int Root2 = InsUnionFind.FindSet(CurrToNode);
if (Root1 == Root2) continue;
InsUnionFind.Unite(CurrFromNode, CurrToNode);
if (mToNodeListDict.ContainsKey(CurrFromNode) == false) {
mToNodeListDict[CurrFromNode] = new List<EdgeInfoDef>();
}
if (mToNodeListDict.ContainsKey(CurrToNode) == false) {
mToNodeListDict[CurrToNode] = new List<EdgeInfoDef>();
}
mToNodeListDict[CurrFromNode].Add(
new EdgeInfoDef() { EdgeID = CurrEdgeID, ToNode = CurrToNode });
mToNodeListDict[CurrToNode].Add(
new EdgeInfoDef() { EdgeID = CurrEdgeID, ToNode = CurrFromNode });
}
Solve();
}
static void Solve()
{
var AnswerList = new List<int>();
while (true) {
// 枝が全部なくなるまで無限ループ
if (mToNodeListDict.Count == 0) {
break;
}
// 任意の葉ノードを探す
int LeafNode = -1;
int LeafNodeConnNode = -1;
foreach (var EachPair in mToNodeListDict) {
if (EachPair.Value.Count == 1) {
LeafNode = EachPair.Key;
LeafNodeConnNode = EachPair.Value[0].ToNode;
break;
}
}
// 葉ノードから該当値をDFSで探して、経路上の値交換を行う
bool IsOK;
List<int> EdgeIDList = DFS(LeafNode, out IsOK);
if (IsOK == false) {
Console.WriteLine(-1);
return;
}
AnswerList.AddRange(EdgeIDList);
// 葉ノードに接続する枝を削除
mToNodeListDict.Remove(LeafNode);
mToNodeListDict[LeafNodeConnNode].RemoveAll(pX => pX.ToNode == LeafNode);
if (mToNodeListDict[LeafNodeConnNode].Count == 0) {
mToNodeListDict.Remove(LeafNodeConnNode);
}
}
Console.WriteLine(AnswerList.Count);
string[] AnswerStr = Array.ConvertAll(AnswerList.ToArray(), pX => pX.ToString());
Console.WriteLine(string.Join(" ", AnswerStr));
}
struct JyoutaiDef
{
internal int CurrInd;
internal List<int> EdgeIDList;
internal List<int> CurrIndList;
}
static List<int> DFS(int pLeafNode, out bool pIsOK)
{
pIsOK = true;
var Stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
WillPush.CurrInd = pLeafNode;
WillPush.EdgeIDList = new List<int>();
WillPush.CurrIndList = new List<int>();
WillPush.CurrIndList.Add(WillPush.CurrInd);
Stk.Push(WillPush);
int GoalInd = Array.IndexOf(mPArr, pLeafNode);
while (Stk.Count > 0) {
JyoutaiDef Popped = Stk.Pop();
// クリア判定
if (Popped.CurrInd == GoalInd) {
// 逆順にする
Popped.EdgeIDList.Reverse();
// 配列の交換を行う
for (int I = Popped.CurrIndList.Count - 1; 1 <= I; I--) {
int Ind1 = Popped.CurrIndList[I];
int Ind2 = Popped.CurrIndList[I - 1];
// 三角交換
int Saved = mPArr[Ind1];
mPArr[Ind1] = mPArr[Ind2];
mPArr[Ind2] = Saved;
}
return Popped.EdgeIDList;
}
if (mToNodeListDict.ContainsKey(Popped.CurrInd) == false) {
continue;
}
foreach (EdgeInfoDef EachEdgeInfo in mToNodeListDict[Popped.CurrInd]) {
// 再訪防止
if (Popped.CurrIndList.Contains(EachEdgeInfo.ToNode)) continue;
WillPush.CurrInd = EachEdgeInfo.ToNode;
WillPush.EdgeIDList = new List<int>(Popped.EdgeIDList);
WillPush.EdgeIDList.Add(EachEdgeInfo.EdgeID);
WillPush.CurrIndList = new List<int>(Popped.CurrIndList);
WillPush.CurrIndList.Add(EachEdgeInfo.ToNode);
Stk.Push(WillPush);
}
}
pIsOK = false;
return null;
}
}
#region UnionFind
// UnionFindクラス
internal class UnionFind
{
private class NodeInfoDef
{
internal int ParentNode;
internal int Rank;
}
private Dictionary<int, NodeInfoDef> mNodeInfoDict =
new Dictionary<int, NodeInfoDef>();
// 要素が1つである木を森に追加
internal void MakeSet(int pNode)
{
NodeInfoDef WillAdd = new NodeInfoDef();
WillAdd.ParentNode = pNode;
WillAdd.Rank = 0;
mNodeInfoDict[pNode] = WillAdd;
}
// 合併処理
internal void Unite(int pX, int pY)
{
int XNode = FindSet(pX);
int YNode = FindSet(pY);
int XRank = mNodeInfoDict[XNode].Rank;
int YRank = mNodeInfoDict[YNode].Rank;
if (XRank > YRank) {
mNodeInfoDict[YNode].ParentNode = XNode;
}
else {
mNodeInfoDict[XNode].ParentNode = YNode;
if (XRank == YRank) {
mNodeInfoDict[YNode].Rank++;
}
}
}
// ノードを引数として、木の根を取得
internal int FindSet(int pTargetNode)
{
// 根までの経路上のノードのList
var PathNodeList = new List<int>();
int CurrNode = pTargetNode;
while (CurrNode != mNodeInfoDict[CurrNode].ParentNode) {
PathNodeList.Add(CurrNode);
CurrNode = mNodeInfoDict[CurrNode].ParentNode;
}
// 経路圧縮 (親ポインタの付け替え)
foreach (int EachPathNode in PathNodeList) {
NodeInfoDef wkNodeInfo = mNodeInfoDict[EachPathNode];
wkNodeInfo.ParentNode = CurrNode;
mNodeInfoDict[EachPathNode] = wkNodeInfo;
}
return CurrNode;
}
internal void DebugPrint()
{
foreach (var EachPair in mNodeInfoDict.OrderBy(pX => pX.Key)) {
Console.WriteLine("mNodeInfoDict[{0}].ParentNode={1}",
EachPair.Key, EachPair.Value.ParentNode);
}
}
}
#endregion